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:
authorCampbell Barton <ideasman42@gmail.com>2009-10-29 23:55:45 +0300
committerCampbell Barton <ideasman42@gmail.com>2009-10-29 23:55:45 +0300
commit4b3fd4a8e05e49a9034e5ee789fcfef3961c19c5 (patch)
tree278aea66d1d901873a8e19f329f7a89c8a434d51 /release/scripts/modules/console
parent8c707b2a5f306f149bcd3057ab6fe91076c75dd8 (diff)
replacement for my own autocomplete module by stani
--- from his patch All the functionality is in the console folder: - intellisense.py: the central module which loads others on demand - complete_namespace: more or less a replacement for the old autocomplete.py - complete_import: module completion (I find this very handy, not just luxury) These complete_* modules work very simple and should also work outside blender. You give some input and it returns a list with possible completions. autocomplete.py is now deprecated.
Diffstat (limited to 'release/scripts/modules/console')
-rw-r--r--release/scripts/modules/console/__init__.py16
-rw-r--r--release/scripts/modules/console/complete_import.py174
-rw-r--r--release/scripts/modules/console/complete_namespace.py67
-rw-r--r--release/scripts/modules/console/intellisense.py100
4 files changed, 357 insertions, 0 deletions
diff --git a/release/scripts/modules/console/__init__.py b/release/scripts/modules/console/__init__.py
new file mode 100644
index 00000000000..eb32d78b1ef
--- /dev/null
+++ b/release/scripts/modules/console/__init__.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2009 www.stani.be (GPL license)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Package for console specific modules."""
diff --git a/release/scripts/modules/console/complete_import.py b/release/scripts/modules/console/complete_import.py
new file mode 100644
index 00000000000..02ded3eef6d
--- /dev/null
+++ b/release/scripts/modules/console/complete_import.py
@@ -0,0 +1,174 @@
+# Copyright (c) 2009 Fernando Perez, www.stani.be (GPL license)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# Original copyright (see docstring):
+#*****************************************************************************
+# Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
+#
+# Distributed under the terms of the BSD License. The full license is in
+# the file COPYING, distributed as part of this software.
+#*****************************************************************************
+
+"""Completer for import statements
+
+Original code was from IPython/Extensions/ipy_completers.py. The following
+changes have been made:
+- ported to python3
+- pep8 polishing
+- limit list of modules to prefix in case of "from w"
+- sorted modules
+- added sphinx documentation
+"""
+
+
+import os
+import sys
+
+TIMEOUT_STORAGE = 3 # Time in secs after which the rootmodules will be stored
+TIMEOUT_GIVEUP = 20 # Time in secs after which we give up
+
+ROOT_MODULES = None
+
+
+def get_root_modules():
+ """
+ Returns a list containing the names of all the modules available in the
+ folders of the pythonpath.
+
+ :returns: modules
+ :rtype: list
+ """
+ global ROOT_MODULES
+ modules = []
+ if not(ROOT_MODULES is None):
+ return ROOT_MODULES
+ from time import time
+ t = time()
+ store = False
+ for path in sys.path:
+ modules += module_list(path)
+ if time() - t >= TIMEOUT_STORAGE and not store:
+ # Caching the list of root modules, please wait!
+ store = True
+ if time() - t > TIMEOUT_GIVEUP:
+ # This is taking too long, we give up.
+ ROOT_MODULES = []
+ return []
+
+ modules += sys.builtin_module_names
+
+ modules = list(set(modules))
+ if '__init__' in modules:
+ modules.remove('__init__')
+ modules = sorted(set(modules))
+ if store:
+ ROOT_MODULES = modules
+ return modules
+
+
+def module_list(path):
+ """
+ Return the list containing the names of the modules available in
+ the given folder.
+
+ :param path: folder path
+ :type path: str
+ :returns: modules
+ :rtype: list
+ """
+
+ if os.path.isdir(path):
+ folder_list = os.listdir(path)
+ elif path.endswith('.egg'):
+ from zipimport import zipimporter
+ try:
+ folder_list = [f for f in zipimporter(path)._files]
+ except:
+ folder_list = []
+ else:
+ folder_list = []
+ #folder_list = glob.glob(os.path.join(path,'*'))
+ folder_list = [p for p in folder_list \
+ if os.path.exists(os.path.join(path, p, '__init__.py'))\
+ or p[-3:] in ('.py', '.so')\
+ or p[-4:] in ('.pyc', '.pyo', '.pyd')]
+
+ folder_list = [os.path.basename(p).split('.')[0] for p in folder_list]
+ return folder_list
+
+
+def complete(line):
+ """
+ Returns a list containing the completion possibilities for an import line.
+
+ :param line:
+
+ incomplete line which contains an import statement::
+
+ import xml.d
+ from xml.dom import
+
+ :type line: str
+ :returns: list of completion possibilities
+ :rtype: list
+
+ >>> complete('import weak')
+ ['weakref']
+ """
+ import inspect
+
+ def try_import(mod, only_modules=False):
+
+ def is_importable(module, attr):
+ if only_modules:
+ return inspect.ismodule(getattr(module, attr))
+ else:
+ return not(attr[:2] == '__' and attr[-2:] == '__')
+
+ try:
+ m = __import__(mod)
+ except:
+ return []
+ mods = mod.split('.')
+ for module in mods[1:]:
+ m = getattr(m, module)
+ if (not hasattr(m, '__file__')) or (not only_modules) or\
+ (hasattr(m, '__file__') and '__init__' in m.__file__):
+ completion_list = [attr for attr in dir(m)
+ if is_importable(m, attr)]
+ completion_list.extend(getattr(m, '__all__', []))
+ if hasattr(m, '__file__') and '__init__' in m.__file__:
+ completion_list.extend(module_list(os.path.dirname(m.__file__)))
+ completion_list = list(set(completion_list))
+ if '__init__' in completion_list:
+ completion_list.remove('__init__')
+ return completion_list
+
+ words = line.split(' ')
+ if len(words) == 3 and words[0] == 'from':
+ return ['import ']
+ if len(words) < 3 and (words[0] in ['import', 'from']):
+ if len(words) == 1:
+ return get_root_modules()
+ mod = words[1].split('.')
+ if len(mod) < 2:
+ mod0 = mod[0]
+ return [m for m in get_root_modules() if m.startswith(mod0)]
+ completion_list = try_import('.'.join(mod[:-1]), True)
+ completion_list = ['.'.join(mod[:-1] + [el]) for el in completion_list]
+ return completion_list
+ if len(words) >= 3 and words[0] == 'from':
+ mod = words[1]
+ return try_import(mod)
diff --git a/release/scripts/modules/console/complete_namespace.py b/release/scripts/modules/console/complete_namespace.py
new file mode 100644
index 00000000000..a2836a60b29
--- /dev/null
+++ b/release/scripts/modules/console/complete_namespace.py
@@ -0,0 +1,67 @@
+# Copyright (c) 2009 www.stani.be (GPL license)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""Autocomplete with the standard library"""
+
+import rlcompleter
+
+TEMP = '__tEmP__' # only \w characters are allowed!
+TEMP_N = len(TEMP)
+
+
+def complete(word, namespace, private=True):
+ """Complete word within a namespace with the standard rlcompleter
+ module. Also supports index or key access [].
+
+ :param word: word to be completed
+ :type word: str
+ :param namespace: namespace
+ :type namespace: dict
+ :param private: whether private attribute/methods should be returned
+ :type private: bool
+
+ >>> complete('fo', {'foo': 'bar'})
+ ['foo']
+ """
+ completer = rlcompleter.Completer(namespace)
+
+ # brackets are normally not allowed -> work around (only in this case)
+ if '[' in word:
+ obj, attr = word.rsplit('.', 1)
+ try:
+ # do not run the obj expression in the console
+ namespace[TEMP] = eval(obj, namespace)
+ except Exception:
+ return []
+ _word = TEMP + '.' + attr
+ else:
+ _word = word
+
+ # find matches with stdlibrary (don't try to implement this yourself)
+ completer.complete(_word, 0)
+ matches = completer.matches
+
+ # brackets are normally not allowed -> clean up
+ if '[' in word:
+ matches = [obj + match[TEMP_N:] for match in matches]
+ del namespace[TEMP]
+
+ # separate public from private
+ public_matches = [match for match in matches if not('._' in match)]
+ if private:
+ private_matches = [match for match in matches if '._' in match]
+ return public_matches + private_matches
+ else:
+ return public_matches
diff --git a/release/scripts/modules/console/intellisense.py b/release/scripts/modules/console/intellisense.py
new file mode 100644
index 00000000000..2658f79a4cc
--- /dev/null
+++ b/release/scripts/modules/console/intellisense.py
@@ -0,0 +1,100 @@
+# Copyright (c) 2009 www.stani.be (GPL license)
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""This module provides intellisense features such as:
+
+* autocompletion
+* calltips (not yet implemented)
+
+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('^import|from.+')
+
+# The following regular expression means a word which:
+# - doesn't start with a quote (quoted words are not py objects)
+# - starts with a [a-zA-Z0-9_]
+# - afterwards dots are allowed as well
+# - square bracket pairs [] are allowed (should be closed)
+RE_UNQUOTED_WORD = re.compile(
+ '''(?:^|[^"'])((?:\w+(?:\w|[.]|\[.+?\])*|))$''', re.UNICODE)
+
+
+def complete(line, cursor, namespace, private=True):
+ """Returns a list of possible completions.
+
+ :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
+ """
+ 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):
+ import complete_import
+ matches = complete_import.complete(line)
+ else:
+ import complete_namespace
+ matches = complete_namespace.complete(word, namespace, 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
+ """
+ matches, word = complete(line, cursor, namespace, private)
+ prefix = os.path.commonprefix(matches)[len(word):]
+ if prefix:
+ line = line[:cursor] + prefix + line[cursor:]
+ cursor += len(prefix)
+ if len(matches) == 1:
+ scrollback = ''
+ else:
+ scrollback = ' '.join([m.split('.')[-1] for m in matches])
+ return line, cursor, scrollback