summaryrefslogtreecommitdiff
path: root/devel/libreadline-java/files/JReadlineCompleter.py
diff options
context:
space:
mode:
Diffstat (limited to 'devel/libreadline-java/files/JReadlineCompleter.py')
-rw-r--r--devel/libreadline-java/files/JReadlineCompleter.py194
1 files changed, 194 insertions, 0 deletions
diff --git a/devel/libreadline-java/files/JReadlineCompleter.py b/devel/libreadline-java/files/JReadlineCompleter.py
new file mode 100644
index 000000000000..9eccfe314aaf
--- /dev/null
+++ b/devel/libreadline-java/files/JReadlineCompleter.py
@@ -0,0 +1,194 @@
+# (X)Emacs: -*- mode: python; coding: latin-1; -*-
+# TAB-Completion for Jython with org.python.util.ReadlineConsole.
+# JReadlineCompleter.py,v 1.1 2007/09/28 08:18:43 martin Exp
+#
+# This is rlcompleter.py from CPython 2.5.1 adapted for Jython
+# and libreadline-java.
+
+"""TAB-completion for Jython + libreadline-java
+
+The completer completes keywords, built-ins and globals in a
+selectable namespace (which defaults to __main__); when completing
+NAME.NAME..., it evaluates (!) the expression up to the last dot and
+completes its attributes.
+
+It's very cool to do "import sys" type "sys.", hit the
+completion key (twice), and see the list of names defined by the
+sys module!
+
+Notes:
+
+- Exceptions raised by the completer function are *ignored* (and
+generally cause the completion to fail). This is a feature -- since
+readline sets the tty device in raw (or cbreak) mode, printing a
+traceback wouldn't work well without some complicated hoopla to save,
+reset and restore the tty state.
+
+- The evaluation of the NAME.NAME... form may cause arbitrary
+application defined code to be executed if an object with a
+__getattr__ hook is found. Since it is the responsibility of the
+application (or the user) to enable this feature, I consider this an
+acceptable risk. More complicated expressions (e.g. function calls or
+indexing operations) are *not* evaluated.
+
+This module is a hacked version of the CPython 2.5 module rlcompleter.
+It is under the PSF (Python Software Foundation) license.
+"""
+
+# CAUTION: Licensing issues may arise when changing the backend
+# library to "GnuReadline" which is under the GPL.
+DEFAULTLIB = "Editline"
+
+# Try to give useful hints for any import failure here:
+import sys
+if not sys.platform.startswith("java"):
+ raise EnvironmentError("Module %s is to be used with Jython only!" %
+ (__name__ == "__main__" and __file__ or __name__))
+if sys.registry["python.console"] != "org.python.util.ReadlineConsole":
+ raise EnvironmentError("You need to set python.console=org.python.util.ReadlineConsole in your ~/.jython file!")
+try:
+ from org.gnu.readline import Readline, ReadlineLibrary, ReadlineCompleter
+except ImportError:
+ raise ImportError("Make sure you have libreadline-java.jar in classpath!")
+import __builtin__
+import atexit
+import keyword
+import os
+import re
+
+__all__ = ["PyCompleter", "JvCompleter"]
+
+Readline.load(
+ getattr(ReadlineLibrary, sys.registry["python.console.readlinelib"], "")
+ or DEFAULTLIB)
+histfile = os.path.join(os.environ["HOME"], ".jyhist")
+try:
+ Readline.readHistoryFile(histfile)
+except:
+ print >> sys.stderr, histfile, "not available!"
+atexit.register(Readline.writeHistoryFile, histfile)
+
+class PyCompleter:
+ def __init__(self, namespace = None):
+ """Create a new completer for the command line.
+
+ PyCompleter([namespace]) -> completer instance.
+
+ If unspecified, the default namespace where completions are performed
+ is __main__ (technically, __main__.__dict__). Namespaces should be
+ given as dictionaries.
+ """
+
+ if namespace and not isinstance(namespace, dict):
+ raise TypeError,'namespace must be a dictionary'
+
+ # Don't bind to namespace quite yet, but flag whether the user wants a
+ # specific namespace or to use __main__.__dict__. This will allow us
+ # to bind to __main__.__dict__ at completion time, not now.
+ if namespace is None:
+ self.use_main_ns = 1
+ else:
+ self.use_main_ns = 0
+ self.namespace = namespace
+
+ def complete(self, text, state):
+ """Return the next possible completion for 'text'.
+
+ This is called successively with state == 0, 1, 2, ... until it
+ returns None. The completion should begin with 'text'.
+
+ """
+ if self.use_main_ns:
+ import __main__
+ self.namespace = __main__.__dict__
+
+ try:
+ if state == 0:
+ if "." in text:
+ self.matches = self.attr_matches(text)
+ else:
+ self.matches = self.global_matches(text)
+ return self.matches[state]
+ except (AttributeError, IndexError, NameError):
+ return None
+
+ def global_matches(self, text):
+ """Compute matches when text is a simple name.
+
+ Return a list of all keywords, built-in functions and names currently
+ defined in self.namespace that match.
+
+ """
+ matches = []
+ n = len(text)
+ for list in [keyword.kwlist,
+ __builtin__.__dict__,
+ self.namespace]:
+ for word in list:
+ if word[:n] == text and word != "__builtins__":
+ matches.append(word)
+ return matches
+
+ def attr_matches(self, text):
+ """Compute matches when text contains a dot.
+
+ Assuming the text is of the form NAME.NAME....[NAME], and is
+ evaluatable in self.namespace, it will be evaluated and its attributes
+ (as revealed by dir()) are used as possible completions. (For class
+ instances, class members are also considered.)
+
+ WARNING: this can still invoke arbitrary C code, if an object
+ with a __getattr__ hook is evaluated.
+
+ """
+ m = re.match(r"(\w+(\.\w+)*)\.(\w*)", text)
+ if not m:
+ return
+ expr, attr = m.group(1, 3)
+ object = eval(expr, self.namespace)
+ words = dir(object)
+ if hasattr(object,'__class__'):
+ words.append('__class__')
+ words = words + get_class_members(object.__class__)
+ matches = []
+ n = len(attr)
+ for word in words:
+ if word[:n] == attr and word != "__builtins__":
+ matches.append("%s.%s" % (expr, word))
+ return matches
+
+def get_class_members(klass):
+ ret = dir(klass)
+ if hasattr(klass,'__bases__'):
+ for base in klass.__bases__:
+ ret = ret + get_class_members(base)
+ return ret
+
+
+class JvCompleter(ReadlineCompleter):
+ """Create a new completer for the command line.
+
+ JvCompleter([completion_callable]) -> completer instance.
+
+ JvCompleter instances should be used as the completion mechanism
+ of Readline via the setCompleter() call.
+ """
+ def __init__(self, realcompleter):
+ self.realcompleter = realcompleter
+ def completer(self, text, state):
+ return self.realcompleter(text, state)
+
+
+pycompleter = PyCompleter()
+jvcompleter = JvCompleter(pycompleter.complete)
+Readline.setCompleter(jvcompleter)
+Readline.parseAndBind("tab: complete")
+try:
+ Readline.setCompletionAppendCharacter('\0')
+except:
+ pass # Method only available from my java-readline patch.
+
+if __name__ == '__main__':
+ print "Sorry, no unit tests yet!"
+
+#EOF#