Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/modules/bl_console_utils/autocomplete/intellisense.py')
-rw-r--r--release/scripts/modules/bl_console_utils/autocomplete/intellisense.py136
1 files changed, 136 insertions, 0 deletions
diff --git a/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py b/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py
new file mode 100644
index 00000000000..e53e38dbc53
--- /dev/null
+++ b/release/scripts/modules/bl_console_utils/autocomplete/intellisense.py
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# Copyright (c) 2009 www.stani.be
+
+"""This module provides intellisense features such as:
+
+* autocompletion
+* calltips
+
+It unifies all completion plugins and only loads them on demand.
+"""
+
+# TODO: file complete if startswith quotes
+import os
+import re
+
+# regular expressions to find out which completer we need
+
+# line which starts with an import statement
+RE_MODULE = re.compile(r'''^import(\s|$)|from.+''')
+
+# The following regular expression means an 'unquoted' word
+RE_UNQUOTED_WORD = re.compile(
+ # don't start with a quote
+ r'''(?:^|[^"'a-zA-Z0-9_])'''
+ # start with a \w = [a-zA-Z0-9_]
+ r'''((?:\w+'''
+ # allow also dots and closed bracket pairs []
+ r'''(?:\w|[.]|\[.+?\])*'''
+ # allow empty string
+ r'''|)'''
+ # allow an unfinished index at the end (including quotes)
+ r'''(?:\[[^\]]*$)?)$''',
+ # allow unicode as theoretically this is possible
+ re.UNICODE)
+
+
+def complete(line, cursor, namespace, private):
+ """Returns a list of possible completions:
+
+ * name completion
+ * attribute completion (obj.attr)
+ * index completion for lists and dictionaries
+ * module completion (from/import)
+
+ :param line: incomplete text line
+ :type line: str
+ :param cursor: current character position
+ :type cursor: int
+ :param namespace: namespace
+ :type namespace: dict
+ :param private: whether private variables should be listed
+ :type private: bool
+ :returns: list of completions, word
+ :rtype: list, str
+
+ >>> complete('re.sr', 5, {'re': re})
+ (['re.sre_compile', 're.sre_parse'], 're.sr')
+ """
+ re_unquoted_word = RE_UNQUOTED_WORD.search(line[:cursor])
+ if re_unquoted_word:
+ # unquoted word -> module or attribute completion
+ word = re_unquoted_word.group(1)
+ if RE_MODULE.match(line):
+ from . import complete_import
+ matches = complete_import.complete(line)
+ if not private:
+ matches[:] = [m for m in matches if m[:1] != "_"]
+ matches.sort()
+ else:
+ from . import complete_namespace
+ matches = complete_namespace.complete(word, namespace, private=private)
+ else:
+ # for now we don't have completers for strings
+ # TODO: add file auto completer for strings
+ word = ''
+ matches = []
+ return matches, word
+
+
+def expand(line, cursor, namespace, *, private=True):
+ """This method is invoked when the user asks autocompletion,
+ e.g. when Ctrl+Space is clicked.
+
+ :param line: incomplete text line
+ :type line: str
+ :param cursor: current character position
+ :type cursor: int
+ :param namespace: namespace
+ :type namespace: dict
+ :param private: whether private variables should be listed
+ :type private: bool
+ :returns:
+
+ current expanded line, updated cursor position and scrollback
+
+ :rtype: str, int, str
+
+ >>> expand('os.path.isdir(', 14, {'os': os})[-1]
+ 'isdir(s)\\nReturn true if the pathname refers to an existing directory.'
+ >>> expand('abs(', 4, {})[-1]
+ 'abs(number) -> number\\nReturn the absolute value of the argument.'
+ """
+ if line[:cursor].strip().endswith('('):
+ from . import complete_calltip
+ matches, word, scrollback = complete_calltip.complete(
+ line, cursor, namespace)
+ prefix = os.path.commonprefix(matches)[len(word):]
+ no_calltip = False
+ else:
+ matches, word = complete(line, cursor, namespace, private)
+ prefix = os.path.commonprefix(matches)[len(word):]
+ if len(matches) == 1:
+ scrollback = ''
+ else:
+ # causes blender bug T27495 since string keys may contain '.'
+ # scrollback = ' '.join([m.split('.')[-1] for m in matches])
+
+ # add white space to align with the cursor
+ white_space = " " + (" " * (cursor + len(prefix)))
+ word_prefix = word + prefix
+ scrollback = '\n'.join(
+ [white_space + m[len(word_prefix):]
+ if (word_prefix and m.startswith(word_prefix))
+ else
+ white_space + m.split('.')[-1]
+ for m in matches])
+
+ no_calltip = True
+
+ if prefix:
+ line = line[:cursor] + prefix + line[cursor:]
+ cursor += len(prefix.encode('utf-8'))
+ if no_calltip and prefix.endswith('('):
+ return expand(line, cursor, namespace, private=private)
+ return line, cursor, scrollback