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:
authorIan Thompson <quornian@googlemail.com>2008-07-15 11:34:46 +0400
committerIan Thompson <quornian@googlemail.com>2008-07-15 11:34:46 +0400
commitaeb4d0c631537d93de084301cac6a5dc981b6655 (patch)
treec82ff43f2732cac35447b657b8adc9306261b74f /release/scripts/textplugin_suggest.py
parentdbb61988fdaa6085912dee6ab8f5569e63ef88fb (diff)
Created a BPy module BPyTextPlugin to centralize functions used across the text plugin scripts. Also created two more scripts to handle imports and member suggestions.
Diffstat (limited to 'release/scripts/textplugin_suggest.py')
-rw-r--r--release/scripts/textplugin_suggest.py327
1 files changed, 44 insertions, 283 deletions
diff --git a/release/scripts/textplugin_suggest.py b/release/scripts/textplugin_suggest.py
index c4fce9ad7a9..8e14dffca9c 100644
--- a/release/scripts/textplugin_suggest.py
+++ b/release/scripts/textplugin_suggest.py
@@ -1,301 +1,62 @@
#!BPY
"""
-Name: 'Suggest'
-Blender: 243
+Name: 'Suggest All'
+Blender: 246
Group: 'TextPlugin'
Shortcut: 'Ctrl+Space'
-Tooltip: 'Suggests completions for the word at the cursor in a python script'
+Tooltip: 'Performs suggestions based on the context of the cursor'
"""
-import bpy, __builtin__, token
-from Blender import Text
-from StringIO import StringIO
-from inspect import *
-from tokenize import generate_tokens
+# Only run if we have the required modules
+try:
+ import bpy
+ from BPyTextPlugin import *
+ OK = True
+except:
+ OK = False
-TK_TYPE = 0
-TK_TOKEN = 1
-TK_START = 2 #(srow, scol)
-TK_END = 3 #(erow, ecol)
-TK_LINE = 4
-TK_ROW = 0
-TK_COL = 1
-
-execs = [] # Used to establish the same import context across defs
-
-keywords = ['and', 'del', 'from', 'not', 'while', 'as', 'elif', 'global',
- 'or', 'with', 'assert', 'else', 'if', 'pass', 'yield',
- 'break', 'except', 'import', 'print', 'class', 'exec', 'in',
- 'raise', 'continue', 'finally', 'is', 'return', 'def', 'for',
- 'lambda', 'try' ]
-
-
-def getBuiltins():
- builtins = []
- bi = dir(__builtin__)
- for k in bi:
- v = getattr(__builtin__, k)
- if ismodule(v): t='m'
- elif callable(v): t='f'
- else: t='v'
- builtins.append((k, t))
- return builtins
-
-
-def getKeywords():
- global keywords
- return [(k, 'k') for k in keywords]
-
-
-def getTokens(txt):
- txt.reset()
- g = generate_tokens(txt.readline)
- tokens = []
- for t in g: tokens.append(t)
- return tokens
-
-
-def isNameChar(s):
- return (s.isalnum() or s == '_')
-
-
-# Returns words preceding the cursor that are separated by periods as a list in
-# the same order
-def getCompletionSymbols(txt):
- (l, c)= txt.getCursorPos()
- lines = txt.asLines()
- line = lines[l]
- a=0
- for a in range(1, c+1):
- if not isNameChar(line[c-a]) and line[c-a]!='.':
- a -= 1
- break
- return line[c-a:c].split('.')
-
-
-def getImports(txt):
- imports = []
-
- # Unfortunately, tokenize may fail if the script leaves brackets or strings
- # open. For now we return an empty list until I have a better idea. Maybe
- # parse manually.
- try:
- tokens = getTokens(txt)
- except:
- return []
-
- for i in range(1, len(tokens)):
-
- # Handle all import statements
- if tokens[i-1][TK_TOKEN] == 'import':
-
- # Find 'from' if it exists
- fr = -1
- for a in range(1, i):
- if tokens[i-a][TK_TYPE] == token.NEWLINE: break
- if tokens[i-a][TK_TOKEN] == 'from':
- fr = i-a
- break
-
- # Handle: import ___[.___][,___[.___]]
- if fr<0:
- parent = ''
-
- # Handle: from ___[.___] import ___[,___]
- else: # fr>=0:
- parent = ''.join([t[TK_TOKEN] for t in tokens[fr+1:i-1]])
-
- module = ''
- while i < len(tokens)-1:
- if tokens[i][TK_TYPE] == token.NAME:
-
- # Get the module name
- module = module + tokens[i][TK_TOKEN]
-
- if tokens[i+1][TK_TOKEN] == '.':
- module += '.'
- i += 1
- else:
- # Add the module name and parent to the dict
- imports.append((module, parent))
- module = ''
-
- elif tokens[i][TK_TOKEN]!=',':
- break
-
- i += 1
-
- # Process imports for: from ___ import *
- for imp,frm in imports:
- print imp, frm
- if frm == '':
- try: __import__(imp)
- except: print '^ERR^'
- else:
- try: __import__(frm, globals(), locals(), [imp])
- except: print '^ERR^'
-
-
-
-# Returns a list of tuples of symbol names and their types (name, type) where
-# type is one of:
-# m (module/class) Has its own members (includes classes)
-# v (variable) Has a type which may have its own members
-# f (function) Callable and may have a return type (with its own members)
-# It also updates the global import context (via execs)
-def getGlobals(txt):
- global execs
-
- # Unfortunately, tokenize may fail if the script leaves brackets or strings
- # open. For now we return an empty list, leaving builtins and keywords as
- # the only globals. (on the TODO list)
- try:
- tokens = getTokens(txt)
- except:
- return []
-
- globals = dict()
- for i in range(len(tokens)):
-
- # Handle all import statements
- if i>=1 and tokens[i-1][TK_TOKEN]=='import':
-
- # Find 'from' if it exists
- fr= -1
- for a in range(1, i):
- if tokens[i-a][TK_TYPE]==token.NEWLINE: break
- if tokens[i-a][TK_TOKEN]=='from':
- fr=i-a
- break
-
- # Handle: import ___[,___]
- if fr<0:
-
- while True:
- if tokens[i][TK_TYPE]==token.NAME:
- # Add the import to the execs list
- x = tokens[i][TK_LINE].strip()
- k = tokens[i][TK_TOKEN]
- execs.append(x)
- exec 'try: '+x+'\nexcept: pass'
-
- # Add the symbol name to the return list
- globals[k] = 'm'
- elif tokens[i][TK_TOKEN]!=',':
- break
- i += 1
-
- # Handle statement: from ___[.___] import ___[,___]
- else: # fr>=0:
-
- # Add the import to the execs list
- x = tokens[i][TK_LINE].strip()
- execs.append(x)
- exec 'try: '+x+'\nexcept: pass'
-
- # Import parent module so we can process it for sub modules
- parent = ''.join([t[TK_TOKEN] for t in tokens[fr+1:i-1]])
- exec 'try: import '+parent+'\nexcept: pass'
-
- # All submodules, functions, etc.
- if tokens[i][TK_TOKEN]=='*':
-
- # Add each symbol name to the return list
- d = eval(parent).__dict__.items()
- for k,v in d:
- if not globals.has_key(k) or not globals[k]:
- t='v'
- if ismodule(v): t='m'
- elif callable(v): t='f'
- globals[k] = t
-
- # Specific function, submodule, etc.
- else:
- while True:
- if tokens[i][TK_TYPE]==token.NAME:
- k = tokens[i][TK_TOKEN]
- if not globals.has_key(k) or not globals[k]:
- t='v'
- try:
- v = eval(parent+'.'+k)
- if ismodule(v): t='m'
- elif callable(v): t='f'
- except: pass
- globals[k] = t
- elif tokens[i][TK_TOKEN]!=',':
- break
- i += 1
-
- elif tokens[i][TK_TYPE]==token.NAME and tokens[i][TK_TOKEN] not in keywords and (i==0 or tokens[i-1][TK_TOKEN]!='.'):
- k = tokens[i][TK_TOKEN]
- if not globals.has_key(k) or not globals[k]:
- t=None
- if (i>0 and tokens[i-1][TK_TOKEN]=='def'):
- t='f'
- else:
- t='v'
- globals[k] = t
-
- return globals.items()
-
-
-def globalSuggest(txt, cs):
- globals = getGlobals(txt)
- return globals
-
-
-# Only works for 'static' members (eg. Text.Get)
-def memberSuggest(txt, cs):
- global execs
+def main():
+ txt = bpy.data.texts.active
+ (line, c) = current_line(txt)
- # Populate the execs for imports
- getGlobals(txt)
+ # Check we are in a normal context
+ if get_context(line, c) != NORMAL:
+ return
- # Sometimes we have conditional includes which will fail if the module
- # cannot be found. So we protect outselves in a try block
- for x in execs:
- exec 'try: '+x+'\nexcept: pass'
+ # Check that which precedes the cursor and perform the following:
+ # Period(.) - Run textplugin_membersuggest.py
+ # 'import' or 'from' - Run textplugin_imports.py
+ # Other - Continue this script (global suggest)
+ pre = get_targets(line, c)
- suggestions = dict()
- (row, col) = txt.getCursorPos()
+ count = len(pre)
- sub = cs[len(cs)-1]
+ if count > 1: # Period found
+ import textplugin_membersuggest
+ textplugin_membersuggest.main()
+ return
+ # Look for 'import' or 'from'
+ elif line.rfind('import ', 0, c) == c-7 or line.rfind('from ', 0, c) == c-5:
+ import textplugin_imports
+ textplugin_imports.main()
+ return
- m=None
- pre='.'.join(cs[:-1])
- try:
- m = eval(pre)
- except:
- print pre+ ' not found or not imported.'
+ list = []
- if m!=None:
- for k,v in m.__dict__.items():
- if ismodule(v): t='m'
- elif callable(v): t='f'
- else: t='v'
- suggestions[k] = t
+ for k in KEYWORDS:
+ list.append((k, 'k'))
- return suggestions.items()
-
-
-def cmp0(x, y):
- return cmp(x[0], y[0])
-
-
-def main():
- txt = bpy.data.texts.active
- if txt==None: return
+ for k, v in get_builtins().items():
+ list.append((k, type_char(v)))
- cs = getCompletionSymbols(txt)
+ for k, v in get_imports(txt).items():
+ list.append((k, type_char(v)))
- if len(cs)<=1:
- l = globalSuggest(txt, cs)
- l.extend(getBuiltins())
- l.extend(getKeywords())
- else:
- l = memberSuggest(txt, cs)
+ for k, v in get_defs(txt).items():
+ list.append((k, 'f'))
- l.sort(cmp=cmp0)
- txt.suggest(l, cs[len(cs)-1])
+ list.sort(cmp = suggest_cmp)
+ txt.suggest(list, pre[-1])
-main()
+if OK:
+ main()