4519 |
4569 |
4520 ################################################################# |
4570 ################################################################# |
4521 ## auto-completion hook interfaces |
4571 ## auto-completion hook interfaces |
4522 ################################################################# |
4572 ################################################################# |
4523 |
4573 |
4524 def addCompletionListHook(self, key, func): |
4574 # TODO: document this hook in chapter 6.2 of plug-in document |
|
4575 def addCompletionListHook(self, key, func, async=False): |
4525 """ |
4576 """ |
4526 Public method to set an auto-completion list provider. |
4577 Public method to set an auto-completion list provider. |
4527 |
4578 |
4528 @param key name of the provider |
4579 @param key name of the provider |
4529 @type str |
4580 @type str |
4530 @param func function providing completion list. func |
4581 @param func function providing completion list. func |
4531 should be a function taking a reference to the editor and |
4582 should be a function taking a reference to the editor and |
4532 a boolean indicating to complete a context. It should return |
4583 a boolean indicating to complete a context. It should return |
4533 the possible completions as a list of strings. |
4584 the possible completions as a list of strings. |
4534 @type function(editor, bool) -> list of str |
4585 @type function(editor, bool) -> list of str in case async is False |
4535 """ |
4586 and function(editor, bool, str) returning nothing in case async |
4536 if key in self.__completionListHookFunctions: |
4587 is True |
|
4588 @param async flag indicating an asynchroneous function |
|
4589 @type bool |
|
4590 """ |
|
4591 if key in self.__completionListHookFunctions or \ |
|
4592 key in self.__completionListAsyncHookFunctions: |
4537 # it was already registered |
4593 # it was already registered |
4538 E5MessageBox.warning( |
4594 E5MessageBox.warning( |
4539 self, |
4595 self, |
4540 self.tr("Auto-Completion Provider"), |
4596 self.tr("Auto-Completion Provider"), |
4541 self.tr("""The completion list provider '{0}' was already""" |
4597 self.tr("""The completion list provider '{0}' was already""" |
4542 """ registered. Ignoring duplicate request.""") |
4598 """ registered. Ignoring duplicate request.""") |
4543 .format(key)) |
4599 .format(key)) |
4544 return |
4600 return |
4545 |
4601 |
4546 if not self.__completionListHookFunctions: |
4602 if not self.__completionListHookFunctions and \ |
|
4603 not self.__completionListAsyncHookFunctions: |
4547 if self.autoCompletionThreshold() > 0: |
4604 if self.autoCompletionThreshold() > 0: |
4548 self.setAutoCompletionThreshold(0) |
4605 self.setAutoCompletionThreshold(0) |
4549 self.SCN_CHARADDED.connect(self.__charAdded) |
4606 self.SCN_CHARADDED.connect(self.__charAdded) |
4550 self.__completionListHookFunctions[key] = func |
4607 |
4551 |
4608 if async: |
|
4609 self.__completionListAsyncHookFunctions[key] = func |
|
4610 else: |
|
4611 self.__completionListHookFunctions[key] = func |
|
4612 |
|
4613 # TODO: document this hook in chapter 6.2 of plug-in document |
4552 def removeCompletionListHook(self, key): |
4614 def removeCompletionListHook(self, key): |
4553 """ |
4615 """ |
4554 Public method to remove a previously registered completion list |
4616 Public method to remove a previously registered completion list |
4555 provider. |
4617 provider. |
4556 |
4618 |
4557 @param key name of the provider |
4619 @param key name of the provider |
4558 @type str |
4620 @type str |
4559 """ |
4621 """ |
4560 if key in self.__completionListHookFunctions: |
4622 if key in self.__completionListHookFunctions: |
4561 del self.__completionListHookFunctions[key] |
4623 del self.__completionListHookFunctions[key] |
4562 |
4624 elif key in self.__completionListAsyncHookFunctions: |
4563 if not self.__completionListHookFunctions: |
4625 del self.__completionListAsyncHookFunctions[key] |
|
4626 |
|
4627 if not self.__completionListHookFunctions and \ |
|
4628 not self.__completionListAsyncHookFunctions: |
4564 self.SCN_CHARADDED.disconnect(self.__charAdded) |
4629 self.SCN_CHARADDED.disconnect(self.__charAdded) |
4565 if self.autoCompletionThreshold() == 0: |
4630 if self.autoCompletionThreshold() == 0: |
4566 self.setAutoCompletionThreshold( |
4631 self.setAutoCompletionThreshold( |
4567 Preferences.getEditor("AutoCompletionThreshold")) |
4632 Preferences.getEditor("AutoCompletionThreshold")) |
4568 |
4633 |
|
4634 # TODO: document this hook in chapter 6.2 of plug-in document |
4569 def getCompletionListHook(self, key): |
4635 def getCompletionListHook(self, key): |
4570 """ |
4636 """ |
4571 Public method to get the registered completion list provider. |
4637 Public method to get the registered completion list provider. |
4572 |
4638 |
4573 @param key name of the provider |
4639 @param key name of the provider |
4574 @type str |
4640 @type str |
4575 @return function providing completion list |
4641 @return function providing completion list |
4576 @rtype function or None |
4642 @rtype function or None |
4577 """ |
4643 """ |
4578 if key in self.__completionListHookFunctions: |
4644 return (self.__completionListHookFunctions.get(key) or |
4579 return self.__completionListHookFunctions[key] |
4645 self.__completionListAsyncHookFunctions.get(key)) |
4580 else: |
|
4581 return None |
|
4582 |
4646 |
4583 def autoComplete(self, auto=False, context=True): |
4647 def autoComplete(self, auto=False, context=True): |
4584 """ |
4648 """ |
4585 Public method to start autocompletion. |
4649 Public method to start auto-completion. |
4586 |
4650 |
4587 @keyparam auto flag indicating a call from the __charAdded method |
4651 @keyparam auto flag indicating a call from the __charAdded method |
4588 (boolean) |
4652 (boolean) |
4589 @keyparam context flag indicating to complete a context (boolean) |
4653 @keyparam context flag indicating to complete a context (boolean) |
4590 """ |
4654 """ |
4591 if auto and self.autoCompletionThreshold() == -1: |
4655 if auto and self.autoCompletionThreshold() == -1: |
4592 # autocompletion is disabled |
4656 # auto-completion is disabled |
4593 return |
4657 return |
4594 |
4658 |
4595 if self.__completionListHookFunctions: |
4659 if self.__completionListHookFunctions or \ |
4596 if self.isListActive(): |
4660 self.__completionListAsyncHookFunctions: |
4597 self.cancelList() |
4661 if auto and Preferences.getEditor("AutoCompletionTimeout"): |
4598 completionsList = [] |
4662 self.__acTimer.stop() |
4599 for key in self.__completionListHookFunctions: |
4663 self.__acContext = context |
4600 completionsList.extend( |
4664 self.__acTimer.start() |
4601 self.__completionListHookFunctions[key](self, context)) |
|
4602 completionsList = list(set(completionsList)) |
|
4603 if len(completionsList) == 0: |
|
4604 if Preferences.getEditor("AutoCompletionScintillaOnFail") and \ |
|
4605 (self.autoCompletionSource() != QsciScintilla.AcsNone or |
|
4606 not auto): |
|
4607 self.autoCompleteQScintilla() |
|
4608 else: |
4665 else: |
4609 completionsList.sort() |
4666 self.__autoComplete(auto, context) |
4610 self.showUserList(EditorAutoCompletionListID, |
|
4611 completionsList) |
|
4612 elif not auto: |
4667 elif not auto: |
4613 self.autoCompleteQScintilla() |
4668 self.autoCompleteQScintilla() |
4614 elif self.autoCompletionSource() != QsciScintilla.AcsNone: |
4669 elif self.autoCompletionSource() != QsciScintilla.AcsNone: |
4615 self.autoCompleteQScintilla() |
4670 self.autoCompleteQScintilla() |
|
4671 |
|
4672 def __autoComplete(self, auto=True, context=None): |
|
4673 """ |
|
4674 Private method to start auto-completion via plug-ins. |
|
4675 |
|
4676 @keyparam auto flag indicating a call from the __charAdded method |
|
4677 (boolean) |
|
4678 @keyparam context flag indicating to complete a context |
|
4679 @type bool or None |
|
4680 """ |
|
4681 line, col = self.getCursorPosition() |
|
4682 text = self.text(line) |
|
4683 if self.__isStartChar(text[col - 1]): |
|
4684 self.__acText = self.getWordLeft(line, col - 1) + text[col - 1] |
|
4685 else: |
|
4686 self.__acText = self.getWordLeft(line, col) |
|
4687 self.__acCompletions.clear() |
|
4688 self.__acCompletionsFinished = 0 |
|
4689 |
|
4690 # Suppress empty completions |
|
4691 if auto and self.__acText == '': |
|
4692 return |
|
4693 |
|
4694 completions = self.__acCache.get(self.__acText) |
|
4695 if completions is not None: |
|
4696 # show list with cached entries |
|
4697 if self.isListActive(): |
|
4698 self.cancelList() |
|
4699 |
|
4700 self.__showCompletionsList(completions) |
|
4701 else: |
|
4702 if context is None: |
|
4703 context = self.__acContext |
|
4704 |
|
4705 for key in self.__completionListAsyncHookFunctions: |
|
4706 self.__completionListAsyncHookFunctions[key]( |
|
4707 self, context, self.__acText) |
|
4708 |
|
4709 for key in self.__completionListHookFunctions: |
|
4710 completions = self.__completionListHookFunctions[key]( |
|
4711 self, context) |
|
4712 self.completionsListReady(completions, self.__acText) |
|
4713 |
|
4714 if Preferences.getEditor("AutoCompletionScintillaOnFail"): |
|
4715 self.__acWatchdog.start() |
|
4716 |
|
4717 # TODO: document this hook in chapter 6.2 of plug-in document |
|
4718 def completionsListReady(self, completions, acText): |
|
4719 """ |
|
4720 Public method to show the completions determined by a completions |
|
4721 provider. |
|
4722 |
|
4723 @param completions list of possible completions |
|
4724 @type list of str or set of str |
|
4725 @param acText text to be completed |
|
4726 @type str |
|
4727 """ |
|
4728 # process the list only, if not already obsolete ... |
|
4729 if acText != self.__acText: |
|
4730 return |
|
4731 |
|
4732 self.__acCompletions.update(set(completions)) |
|
4733 |
|
4734 self.__acCompletionsFinished += 1 |
|
4735 # Got all results from auto completer? |
|
4736 if self.__acCompletionsFinished >= len( |
|
4737 self.__completionListAsyncHookFunctions): |
|
4738 self.__acWatchdog.stop() |
|
4739 |
|
4740 # Autocomplete with QScintilla if no results present |
|
4741 if (Preferences.getEditor("AutoCompletionScintillaOnFail") |
|
4742 and not self.__acCompletions): |
|
4743 self.autoCompleteQScintilla() |
|
4744 return |
|
4745 |
|
4746 # ... or completions are not empty |
|
4747 if not bool(completions): |
|
4748 return |
|
4749 |
|
4750 if self.isListActive(): |
|
4751 self.cancelList() |
|
4752 |
|
4753 if self.__acCompletions: |
|
4754 self.__acCache.add(acText, set(self.__acCompletions)) |
|
4755 self.__showCompletionsList(self.__acCompletions) |
|
4756 |
|
4757 def __showCompletionsList(self, completions): |
|
4758 """ |
|
4759 Private method to show the completions list. |
|
4760 |
|
4761 @param completions completions to be shown |
|
4762 @type list of str or set of str |
|
4763 """ |
|
4764 if Preferences.getEditor("AutoCompletionReversedList"): |
|
4765 acCompletions = sorted( |
|
4766 list(completions), |
|
4767 key=self.__replaceLeadingUnderscores) |
|
4768 else: |
|
4769 acCompletions = sorted(list(completions)) |
|
4770 self.showUserList(EditorAutoCompletionListID, acCompletions) |
|
4771 |
|
4772 def __replaceLeadingUnderscores(self, txt): |
|
4773 """ |
|
4774 Private method to replace the first two underlines for invers sorting. |
|
4775 |
|
4776 @param txt completion text |
|
4777 @type str |
|
4778 @return modified completion text |
|
4779 @rtype str |
|
4780 """ |
|
4781 if txt.startswith('_'): |
|
4782 return txt[:2].replace('_', '~') + txt[2:] |
|
4783 else: |
|
4784 return txt |
|
4785 |
|
4786 def __clearCompletionsCache(self): |
|
4787 """ |
|
4788 Private method to clear the auto-completions cache. |
|
4789 """ |
|
4790 self.__acCache.clear() |
4616 |
4791 |
4617 def __completionListSelected(self, listId, txt): |
4792 def __completionListSelected(self, listId, txt): |
4618 """ |
4793 """ |
4619 Private slot to handle the selection from the completion list. |
4794 Private slot to handle the selection from the completion list. |
4620 |
4795 |
4650 |
4825 |
4651 @return flag indicating the availability of dynamic auto-completion |
4826 @return flag indicating the availability of dynamic auto-completion |
4652 (boolean) |
4827 (boolean) |
4653 """ |
4828 """ |
4654 return (self.acAPI or |
4829 return (self.acAPI or |
4655 bool(self.__completionListHookFunctions)) |
4830 bool(self.__completionListHookFunctions) or |
|
4831 bool(self.__completionListAsyncHookFunctions)) |
|
4832 |
|
4833 ################################################################# |
|
4834 ## call-tip hook interfaces |
|
4835 ################################################################# |
|
4836 |
|
4837 # TODO: document this hook in chapter 6.2 of plug-in document |
|
4838 def addCallTipHook(self, key, func): |
|
4839 """ |
|
4840 Public method to set a calltip provider. |
|
4841 |
|
4842 @param key name of the provider |
|
4843 @type str |
|
4844 @param func function providing calltips. func |
|
4845 should be a function taking a reference to the editor, |
|
4846 a position into the text and the amount of commas to the |
|
4847 left of the cursor. It should return the possible |
|
4848 calltips as a list of strings. |
|
4849 @type function(editor, int, int) -> list of str |
|
4850 """ |
|
4851 if key in self.__ctHookFunctions: |
|
4852 # it was already registered |
|
4853 E5MessageBox.warning( |
|
4854 self, |
|
4855 self.tr("Call-Tips Provider"), |
|
4856 self.tr("""The call-tips provider '{0}' was already""" |
|
4857 """ registered. Ignoring duplicate request.""") |
|
4858 .format(key)) |
|
4859 return |
|
4860 |
|
4861 self.__ctHookFunctions[key] = func |
|
4862 |
|
4863 # TODO: document this hook in chapter 6.2 of plug-in document |
|
4864 def removeCallTipHook(self, key): |
|
4865 """ |
|
4866 Public method to remove a previously registered calltip provider. |
|
4867 |
|
4868 @param key name of the provider |
|
4869 @type str |
|
4870 """ |
|
4871 if key in self.__ctHookFunctions: |
|
4872 del self.__ctHookFunctions[key] |
|
4873 |
|
4874 # TODO: document this hook in chapter 6.2 of plug-in document |
|
4875 def getCallTipHook(self, key): |
|
4876 """ |
|
4877 Public method to get the registered calltip provider. |
|
4878 |
|
4879 @param key name of the provider |
|
4880 @type str |
|
4881 @return function providing calltips |
|
4882 @rtype function or None |
|
4883 """ |
|
4884 if key in self.__ctHookFunctions: |
|
4885 return self.__ctHookFunctions[key] |
|
4886 else: |
|
4887 return None |
|
4888 |
|
4889 def canProvideCallTipps(self): |
|
4890 """ |
|
4891 Public method to test the calltips availability. |
|
4892 |
|
4893 @return flag indicating the availability of calltips (boolean) |
|
4894 """ |
|
4895 return (self.acAPI or |
|
4896 bool(self.__ctHookFunctions)) |
4656 |
4897 |
4657 def callTip(self): |
4898 def callTip(self): |
4658 """ |
4899 """ |
4659 Public method to show calltips. |
4900 Public method to show calltips. |
4660 """ |
4901 """ |
4782 else: |
5023 else: |
4783 ct = ct - ctshift |
5024 ct = ct - ctshift |
4784 return ct |
5025 return ct |
4785 |
5026 |
4786 ################################################################# |
5027 ################################################################# |
4787 ## call-tip hook interfaces |
5028 ## Methods needed by the code documentation viewer |
4788 ################################################################# |
5029 ################################################################# |
4789 |
5030 |
4790 def addCallTipHook(self, key, func): |
5031 def __charAddedPermanent(self, charNumber): |
4791 """ |
5032 """ |
4792 Public method to set a calltip provider. |
5033 Private slot called to handle the user entering a character. |
4793 |
5034 |
4794 @param key name of the provider |
5035 Note: This slot is always connected independent of the auto-completion |
4795 @type str |
5036 and calltips handling __charAdded() slot. |
4796 @param func function providing calltips. func |
5037 |
4797 should be a function taking a reference to the editor, |
5038 @param charNumber value of the character entered (integer) |
4798 a position into the text and the amount of commas to the |
5039 """ |
4799 left of the cursor. It should return the possible |
5040 char = chr(charNumber) |
4800 calltips as a list of strings. |
5041 if char == "(" and \ |
4801 @type function(editor, int, int) -> list of str |
5042 Preferences.getDocuViewer("ShowInfoOnOpenParenthesis"): |
4802 """ |
5043 self.vm.showEditorInfo(self) |
4803 if key in self.__ctHookFunctions: |
5044 |
4804 # it was already registered |
5045 def __showCodeInfo(self): |
4805 E5MessageBox.warning( |
5046 """ |
4806 self, |
5047 Private slot to handle the context menu action to show code info. |
4807 self.tr("Call-Tips Provider"), |
5048 """ |
4808 self.tr("""The call-tips provider '{0}' was already""" |
5049 self.vm.showEditorInfo(self) |
4809 """ registered. Ignoring duplicate request.""") |
|
4810 .format(key)) |
|
4811 return |
|
4812 |
|
4813 self.__ctHookFunctions[key] = func |
|
4814 |
|
4815 def removeCallTipHook(self, key): |
|
4816 """ |
|
4817 Public method to remove a previously registered calltip provider. |
|
4818 |
|
4819 @param key name of the provider |
|
4820 @type str |
|
4821 """ |
|
4822 if key in self.__ctHookFunctions: |
|
4823 del self.__ctHookFunctions[key] |
|
4824 |
|
4825 def getCallTipHook(self, key): |
|
4826 """ |
|
4827 Public method to get the registered calltip provider. |
|
4828 |
|
4829 @param key name of the provider |
|
4830 @type str |
|
4831 @return function providing calltips |
|
4832 @rtype function or None |
|
4833 """ |
|
4834 if key in self.__ctHookFunctions: |
|
4835 return self.__ctHookFunctions[key] |
|
4836 else: |
|
4837 return None |
|
4838 |
|
4839 def canProvideCallTipps(self): |
|
4840 """ |
|
4841 Public method to test the calltips availability. |
|
4842 |
|
4843 @return flag indicating the availability of calltips (boolean) |
|
4844 """ |
|
4845 return (self.acAPI or |
|
4846 bool(self.__ctHookFunctions)) |
|
4847 |
5050 |
4848 ################################################################# |
5051 ################################################################# |
4849 ## Methods needed by the context menu |
5052 ## Methods needed by the context menu |
4850 ################################################################# |
5053 ################################################################# |
4851 |
5054 |