使用python模拟命令行终端的示例

可以对?显示帮助信息,需要立即获取输入的字符,因此需要用到termios模块

另外需要对tab键做处理,当按下tab键时可以进行自动补全

#! /usr/bin/env python
# coding=utf-8

import os
import sys
import tty
import termios

'''
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

class CLI(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)
  def getch(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)
    return ch
  def completer_kw_update(self):
    self.completer_dict_keys = self.completer_dict.keys()
    self.completer_dict_keys.sort()
    self.completer_cnt = len(self.completer_dict)
  def completer_kw_add(self, key, word):
    self.completer_dict[key] = word
    self.completer_kw_update()
  def completer_kw_clear(self):
    self.completer_dict.clear()
    self.completer_id_update()
  def completer_id_update(self):
    self.completer_kw_update()
    if self.completer_id < self.completer_cnt - 1:
      self.completer_id += 1
    else:
      self.completer_id = 0
  def completer_wd_select(self, word):
    if not word:
      return ''
    cnt = self.completer_cnt
    while cnt>0:
      completer = self.completer_dict_keys[self.completer_id]
      self.completer_id_update()
      cnt -= 1
      if word == completer[:len(word)]:
        return completer[len(word):]
    return ''
  def printf(self, info=''):
    sys.stdout.write(info)
  def show_spec_len_str(self, info, maxlen, spacech=' '):
    'display a string of the specified length'
    maxlen = maxlen
    infolen = len(info)
    if maxlen < infolen:
      maxlen = infolen
    while infolen>0:
      ch = info[-infolen]
      for i in range(self.char_memory_len(ch)):
        self.printf(info[i-infolen])
      infolen -= self.char_memory_len(ch)
      maxlen -= self.char_display_len(ch)
    while maxlen>0:
      self.printf(spacech)
      maxlen -= self.char_display_len(spacech)
  def show_help_info(self):
    if self.completer_on:
      line = self.line_complete
    else:
      line = self.line
    lastwd = ''
    show_all = False
    if not line or line[-1] == ' ':
      show_all = True
    else:
      lastwd = line.split()[-1]
    if self.completer_dict:
      maxlen = max([len(info) for info in self.completer_dict])
    else:
      maxlen = 12
    for info in self.completer_dict:
      if show_all or lastwd == info[:len(lastwd)]:
        self.printf(' ')
        self.show_spec_len_str(info, maxlen)
        self.printf(' ')
        self.printf(self.completer_dict[info])
        self.printf('\r\n')
  def is_chinese_char(self, ch):
    return ord(ch) > 127
  def char_display_len(self, ch):
    if self.is_chinese_char(ch):
      return 2
    elif ord(ch) == CLI_KEY_TAB:
      return CLI_KEY_TABLEN
    else:
      return 1
  def char_memory_len(self, ch):
    if self.is_chinese_char(ch):
      return 3
    else:
      return 1
  def rm_last_char(self, line):
    lastch = ''
    rmlen = 0
    if len(line)>0:
      lastch = line[-1]
      self.printf('\b \b' * self.char_display_len(lastch))
      rmlen = self.char_memory_len(lastch)
      if len(line) >= rmlen:
        line = line[:-(rmlen)]
      else:
        rmlen = len(line)
        line = ''
    return rmlen, line
  def rm_last_word(self, line):
    lastwd = ''
    linelen = len(line)
    rspacelen = linelen - len(line.rstrip())
    if not linelen:
      return line
    lastwd = line.split()[-1]
    backlen = len(lastwd) + rspacelen
    rmlen = 0
    while backlen>0 and line:
      rmlen, line = self.rm_last_char(line)
      backlen -= rmlen
    return line
  def rm_one_line(self, line):
    rmlen = 0
    while line:
      rmlen, line = self.rm_last_char(line)
    return line
  def do_line_complete_proc(self):
    line = self.line
    line_complete = self.line_complete
    lastwd = ''
    self.printf('\r\n')
    if self.line_complete:
      self.printf(self.line_complete)
    else:
      self.printf(self.line)
    if not line:
      return line
    lastwd = line.split()[-1]
    completer = self.completer_wd_select(lastwd)
    if not completer.strip():
      self.line_complete = line
      return line
    backlen = len(line_complete) - len(line)
    while backlen>0 and line_complete:
      rmlen, line_complete = self.rm_last_char(line_complete)
      backlen -= rmlen
    self.printf(completer)
    line_complete = line + completer
    self.line_complete = line_complete
  def do_line_complete_end(self):
    if self.completer_on:
      self.line = self.line_complete
      self.line_complete = ''
      self.completer_on = False
  def get_line(self):
    self.line = ''
    self.line_complete = ''
    self.completer_on = False
    while True:
      ch = self.getch()
      if ch == '\r' or ch == '\n':
        self.do_line_complete_end()
        self.printf('\r\n')
        break
      elif ord(ch) == CLI_KEY_BACK or ord(ch) == CLI_KEY_CTRLH:
        if self.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()
      elif ord(ch) == CLI_KEY_QMARK:
        self.printf('?')
        self.printf('\r\n')
        self.show_help_info()
        if self.completer_on:
          self.printf(self.line_complete)
        else:
          self.printf(self.line)
      elif ord(ch) == CLI_KEY_CTRLW:
        if self.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()
      elif ord(ch) == CLI_KEY_TAB:
        self.completer_on = True
        self.do_line_complete_proc()
      elif ord(ch) == CLI_KEY_CTRLD:
        if self.line:
          return self.line
        else:
          return ch
      elif ord(ch) == CLI_KEY_QUIT:
        self.printf('\r\n Interrupted by <Ctrl-\>.\r\n')
        sys.exit()
      elif ord(ch) == CLI_KEY_CTRLU:
        if self.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()
      elif ord(ch) == CLI_KEY_SPACE:
        self.printf(ch)
        if self.completer_on:
          self.line_complete += ch
        else:
          self.line += ch
      else:
        self.printf(ch)
        self.do_line_complete_end()
        self.line += ch
        # chinese qmask proc
        if ord(ch) == 159 and len(self.line)>= 3 and self.line[-3:] == '\xef\xbc\x9f':
          self.printf('\r\n')
          self.line = self.line[:-3]
          self.show_help_info()
          self.printf(self.line)
    return self.line
  def get_raw_line(self):
    self.raw_line = ''
    while True:
      ch = self.getch()
      if ch == '\r' or ch == '\n':
        self.printf('\r\n')
        break
      elif ord(ch) == CLI_KEY_BACK or ord(ch) == CLI_KEY_CTRLH:
        rmlen, self.raw_line = self.rm_last_char(self.raw_line)
      elif ord(ch) == CLI_KEY_CTRLW:
        self.raw_line = self.rm_last_word(self.raw_line)
      elif ord(ch) == CLI_KEY_TAB:
        self.printf(' ' * self.char_display_len(ch))
        self.raw_line += ch
      elif ord(ch) == CLI_KEY_CTRLD:
        if self.raw_line:
          return self.raw_line
        else:
          return ch
      elif ord(ch) == CLI_KEY_QUIT:
        self.printf('\r\n Interrupted by <Ctrl-\>.\r\n')
        sys.exit()
      elif ord(ch) == CLI_KEY_CTRLU:
        self.raw_line = self.rm_one_line(self.raw_line)
      else:
        self.raw_line += ch
        self.printf(ch)
    return self.raw_line

def test():
  cli = CLI()
  help_info = {
  	'hello0':   'say hello 0',
  	'hello1':   'say hello 1',
  	'hellohello': 'say hello hello',
  	'hellohehe': 'say hello hehe',
  	'hellohi':  'say hello hi',
  	'你好啊':   'say 你好啊',
  	'你好吗':   'say 你好吗',
  	'你好哈':   'say 你好哈',
  	}
  for key in help_info:
    cli.completer_kw_add(key, help_info[key])
  while True:
    line = cli.get_line()
    if len(line) == 1 and ord(line[0]) == CLI_KEY_CTRLD:
      break
    if line == 'quit':
      break
    print(line)

if __name__ == "__main__":
  test()

以上这篇使用python模拟命令行终端的示例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Python彩色化Linux的命令行终端界面的代码实例分享

    先看看效果: 在linux的终端中,ANSI转义序列来控制颜色 基本规则: 前面加上\033[,结尾用\033[0m重置为原来的颜色 可以在终端中输入下面这句,就可以看到输出绿色的hello. >>echo -e '\033[0;32mhello\033[0m' 其中0;32m控制颜色. 最简单的,只要把0;32m中的2改成0-7,就对应不同颜色了. 利用这点,在python中,可以这样来. #coding=utf-8 fmt = '\033[0;3{}m{}\033[0m'.format c

  • 在Linux命令行终端中使用python的简单方法(推荐)

    Linux终端中的操作均是使用命令行来进行的.因此,对于小白来说,熟记几个基本的命令行和使用方法能够较快的在Linux命令行环境中将python用起来. 打开命令行窗口 打开命令行窗口的快捷键如下: Ctrl + Alt + t 关闭名命令行窗口 关闭命令行窗口的快捷键如下: Ctrl + d 进入python环境 在命令行中直接输入python即进入了python的编辑环境.进入环境后最明显的提示是:光标由-$变成>>>. 退出python环境 使用ctrl +d的方式退出python

  • 在linux的终端退出python命令行的方法

    如下所示: Python 2.7.7 (default, Jun 3 2014, 01:46:20) [GCC 4.9.0 20140521 (prerelease)] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> quitUse quit() or Ctrl-D (i.e. EOF) to

  • 使用python模拟命令行终端的示例

    可以对?显示帮助信息,需要立即获取输入的字符,因此需要用到termios模块 另外需要对tab键做处理,当按下tab键时可以进行自动补全 #! /usr/bin/env python # coding=utf-8 import os import sys import tty import termios ''' 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 '''

  • python argparse命令行参数解析(推荐)

    argparse是python用于解析命令行参数和选项的标准模块. 很多时候,需要用到解析命令行参数的程序,目的是在终端窗口输入训练的参数和选项. argparse 模块可以让人轻松编写用户友好的命令行接口. 程序定义它需要的参数,然后 argparse 将弄清如何从 sys.argv 解析出那些参数. argparse 模块还会自动生成帮助和使用手册,并在用户给程序传入无效参数时报出错误信息. test.py # -*- coding: utf-8 -*- import argparse #

  • 用Python实现命令行闹钟脚本实例

    前言: 这篇文章给大家介绍了怎样用python创建一个简单的报警,它可以运行在命令行终端,它需要分钟做为命令行参数,在这个分钟后会打印"wake-up"消息,并响铃报警,你可以用0分钟来测试,它会立即执行,用扬声器控制面板调整声音. 以下是脚本: # alarm_clock.py # Description: A simple Python program to make the computer act # like an alarm clock. Start it running

  • python解析命令行参数的三种方法详解

    这篇文章主要介绍了python解析命令行参数的三种方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python解析命令行参数主要有三种方法:sys.argv.argparse解析.getopt解析 方法一:sys.argv -- 命令行执行:python test_命令行传参.py 1,2,3 1000 # test_命令行传参.py import sys def para_input(): print(len(sys.argv)) #

  • Python的命令行参数实例详解

    目录 0.命令行参数 1.sys.argv 2.getopt 2.1getopt.getopt方法 2.2Exceptiongetopt.GetoptError 3.argparse 总结 0. 命令行参数 通常,对于大型项目程序而言,执行程序的一个必要的步骤是正确处理命令行参数,这些命令行参数是提供给包含某种参数化信息的程序或脚本的参数.例如,在计算机视觉项目中,图像和不同类型的文件通常作为命令行参数传递给脚本,用于使程序可以处理不同图片或者不同类型文件. 命令行参数是参数化程序执行的一种常见

  • Python 添加命令行参数步骤

    目录 前言 添加命令行参数的一般步骤 命令行参数示例 前言 许多任务程序如果为其构造为一个命令行界面,就可以通过接受不同的参数来改变它的工作方式.例如,在爬虫程序中,不同 URL 通常可以作为命令行参数传递给任务程序,从而可以爬取不同网页中的数据.在 Python 标准库中包含一个强大的 argparse 模块,可以轻松创建丰富的命令行参数解析. 添加命令行参数的一般步骤 在程序脚本中, argparse 的基本使用方式可以分三个步骤显示: 定义脚本要接受的参数,生成新的参数解析器 调用定义的解

  • Python调用命令行进度条的方法

    本文实例讲述了Python调用命令行进度条的方法.分享给大家供大家参考.具体分析如下: 关键点是输出'\r'这个字符可以使光标回到一行的开头,这时输出其它内容就会将原内容覆盖. import time import sys def progress_test(): bar_length=20 for percent in xrange(0, 100): hashes = '#' * int(percent/100.0 * bar_length) spaces = ' ' * (bar_lengt

  • Python实现命令行通讯录实例教程

    1.实现目标 编写一个命令行通讯录程序,可以添加.查询.删除通讯录好友及电话 2.实现方法 创建一个类来表示一个人的信息.使用字典存储每个人的对象,名字作为键. 使用pickle模块永久地把这些对象存储下来. 使用字典内建的方法添加.删除修改人员信息. 3.思维导图 4.编写伪代码 # 1.创建字典用来存储通讯录信息 # 2.创建人员类,包含姓名.关系.电话三个属性 # 3.创建操作类,包含增加.查询.删除人员,退出,保存并退出五个方法 # 4.程序运行 # 5.判断通讯录文件是否存在 # 6.

  • Python 获得命令行参数的方法(推荐)

    本篇将介绍python中sys, getopt模块处理命令行参数 如果想对python脚本传参数,python中对应的argc, argv(c语言的命令行参数)是什么呢? 需要模块:sys 参数个数:len(sys.argv) 脚本名:    sys.argv[0] 参数1:     sys.argv[1] 参数2:     sys.argv[2] test.py import sys print "脚本名:", sys.argv[0] for i in range(1, len(sy

随机推荐