Sunday, November 30, 2008

[Python]实现Console下路径输入的补全

因为要用脚本处理一些log,每次运行都要输入待处理的log的路径。可是我存放的log路径太复杂 log自己名字也很复杂,输入起来很麻烦。就想在python里借用shell的路径补全功能。Python里有readline这个module可以提供补全的基本功能,当然需要你自己给它一个completer(text, state)函数从而使它知道如何去补全。另外还有一个cmd module提供简单的命令行界面。用这两者就可以实现我们需要的功能。
import cmd
import string, sys
import os
import readline
class CLI(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self, "tab")
self.prompt = 'input the path:'
self.path = None
readline.set_completer_delims('/\\')
def onecmd(self, path):
if os.path.exists(path):
self.path = path
return path
else:
print "%s not exists"%(path)
return None
def complete(self, text, state):
if state == 0:
origline = readline.get_line_buffer()
line = origline.lstrip()
stripped = len(origline) - len(line)
begidx = readline.get_begidx() - stripped
endidx = readline.get_endidx() - stripped
self.completion_matches = self.completepaths(text, line, begidx, endidx)
try:
return self.completion_matches[state]
except IndexError:
return None
def completepaths(self, text, line, *ignored):
(head, tail) = os.path.split(line)
matches = []
if head == "":
p = "."
else:
p = head
if os.path.exists(p):
filelist = os.listdir(p)
matches = [f if os.path.isfile(os.path.join(head, f))\
else f+os.sep for f in filelist if f.startswith(tail)]
return matches
def get_path(self):
self.cmdloop()
return self.path
def get_path():
cli = CLI()
return cli.get_path()

这里我们继承了Cmd类。但是重载了complete这个函数。这个函数是在用户按下tab键呼叫补全的时候被调用。
使用这个小程序只要import这个文件以后直接调用get_path就可以了.
补充:后来发现了一个小bug已经做了修改。cmd module里面在cmdloop()这个函数里就设定了completer_delims (分隔符)。问题在于默认的分隔符里面有很多合法的linux文件名字符比如 “-”这样会导致tab补全的时候出一些问题。 所以我们需要在这之前设置好。这里我们就在__init__初始化的时候设置成/以及\。

No comments: