2012-07-09 4 views
3

나는 지금 PyQT GUI를 만들고있는 커맨드 라인 툴로 작업 해왔다. readline 모듈을 사용하여 현재의 자동 완성 구현을 가져 와서 QLineEdit 텍스트 상자에 입력하고 싶습니다. 이것이 가능한가? 추천이 있으십니까? 나는 QLineEdit 위젯에서 작동하도록 작성한 Readline 모듈을 얻을 수없는 경우, 내가 궁극적으로 무엇을하고 싶습니다,PyQt LineDisit with readline completer?

import readline 

values = ['these','are','my','autocomplete','words'] 
completions = {} 

def completer(text,state): 
    try: 
     matches = completions[text] 
    except KeyError: 
     matches = [value for value in values if text.upper() in value.upper()] 
     completions[text] = matches 
    try: 
     return matches[state] 
    except IndexError: 
     return None 

readline.set_completer(completer) 
readline.parse_and_bind('tab: menu-complete') 

whie 1: 
    text = raw_input('> ') 
    text.dostuff() 

궁극적 : 여기

내가 작성한 Readline 모듈을하고있어 물건의 예 해야할 일은 여러 단어를 + - * /() 등의 기호로 구분하여 단어 목록을 작성하는 것입니다.

고마워요!

답변

4

나는 먼저 새로운 기능을 중심으로 QCompleter를 시도하고 포장하는 것이 큰 고통임을 알 수 있습니다. Qcompleter의 모든 인터페이스를 만족시킬 수 있어야하며, realine 코드 주위에서 연결해야합니다.

QCompleter에 설정된 QStringListModel을 수동으로 업데이트하고 주어진 검색 접두어에 대한 현재 완료 및 총 완료 수를 가져와야합니다. 여기

가 PopupCompletion 모드와 호환되는 작업 예제 다음 _completionAt() 방법

import re 

class ReadlineCompleter(QtGui.QCompleter): 

    def __init__(self, completeFn, *args, **kwargs): 
     super(ReadlineCompleter, self).__init__(*args, **kwargs) 
     self._completer = completeFn 
     self.setModel(QtGui.QStringListModel()) 
     self.update() 

    def setCompletionPrefix(self, val): 
     super(ReadlineCompleter, self).setCompletionPrefix(val) 
     self.update() 

    def currentCompletion(self): 
     state = self.currentRow() 
     return self._completionAt(state) 

    def completionCount(self): 
     state = 0 
     while True: 
      result = self._completionAt(state) 
      if not result: 
       break 
      state += 1 
     return state 

    def update(self): 
     matches = [self._completionAt(i) for i in xrange(self.completionCount())] 
     self.model().setStringList(matches) 

    def _completionAt(self, state): 
     text = str(self.completionPrefix()) 

     # regex to split on any whitespace, or the char set +*/^()- 
     match = re.match(r'^(.*)([\s+*/^()-]+)(.*)$', text) 
     if match: 
      prefix, sep, text = match.groups() 

     result = self._completer(str(text), state) 

     if result and match: 
      result = sep.join([prefix, result]) 

     return '' if result is None else result  

공지 사항, 나는 분리 패턴을 검출, 당신이 원하는 추가 기능을 추가했습니다. 이것을 분명히 조정할 수 있습니다. 그러나 마지막 부분을 분리하여 해당 값을 사용하여 완료를 확인한 다음 결과를 다시 접두어로 다시 결합합니다.

사용

중요. 업데이트를 강제로 수행하려면 QLineEdit의 신호 인 textChanged을 완료 자에게 연결해야합니다. 그렇지 않으면 어떤 기능도 완성 자에서 사용되지 않습니다.

line = QtGui.QLineEdit() 
comp = ReadlineCompleter(completer) 
comp.setCompletionMode(comp.PopupCompletion) 
line.setCompleter(comp) 
# important 
line.textChanged.connect(comp.setCompletionPrefix) 

다른 사람들이 완전히 completer의 표준 신호 주위에 가서 스스로를 트리거 사용자 정의 라인 편집의 기능을 작성해야했다 방법을 보여 examples here있다. 약간의 노력을 볼 수 있습니다.

+0

readline 모듈에서 제공되는이 기능에서 얻으려는 기능 만 여러 단어에 걸쳐 탭 완성을 계속합니다. "땅 돼지-aardw을"및 탭을 공격 한 후 전체를 전자 근래 : 예를 들어, 단어의 내 목록 땅 돼지 내가 입력 할 수 있도록하려는 땅 늑대됩니다. 어떤 아이디어? 죄송합니다. 간단한 문제라면 PyQt를 처음 접했습니다 ... –

+0

좋아, QLineEdit을 서브 클래 싱하지 않고이 작업을 할 수있는 가장 가까운 부분을 알았습니다. 또한 분리 기호를 감지하고 계속 완료하는 데 대한 부분을 추가했습니다. – jdi

+0

우수한 덕분에 당신의 도움에 아주 많이 감사합니다! 현재 구현하고 있지 않은 두 가지 사항이 있습니다. 하나는 하이픈에 대해서만 분리된다는 것이고, OP에서는 + - */^()와 같은 여러 연산자로 분리하려고한다고 언급했습니다. 정규식에 대한 나의 지식은 사실 0이지만, 나는 그것을 달성 할 수 있다고 생각 하는가? 두 번째로, 이것은 한 번만 분리됩니다. 예를 들어, 단어 목록에서 바벨과 일치시키기 위해 'aardvark + aardwolves * bab'을하면 탭 완성을 원합니다. 생각? –