ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Completer with history viewer support and more features
Submitter: Sunjoong LEE (other recipes)
Last Updated: 2006/06/29
Version no: 2.9
Category:

 

Not Rated yet


Description:

This module let "tab" key can indent and completing valid python identifiers, keywords, and filenames.
This module support history view also.

Note1: original python rlcompleter module only avail in unix-like environment
Note2: if you seek a more simple completer you could try Jian Ding Chen's recipe at: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/496812

Source: Text Source

# History.py
#
# Store the file "History.py"
# in site-packages directory like "/usr/lib/python2.4/site-packages,"
# or a directory pointed by PYTHONPATH environment varable,
# or your home directory.
#
# Insert the line, "import History" to "~/.pystartup" file,
# and set an environment variable to point to it:
# "export PYTHONSTARTUP=${HOME}/.pystartup" in bash.
#
# References:
#     Guido van Rossum. Python Tutorial. Python Sfotware Foundation, 2005. 86
#     Jian Ding Chen. Indentable rlcompleter. Python Cookbook Recipe 496812
#     Guido van Rossum. rlcompleter.py. Python Sfotware Foundation, 2005
#
# 2006.06.29 Sunjoong LEE <sunjoong@gmail.com>
#
__author__ = 'Sunjoong LEE <sunjoong@gmail.com>'
__date__ = '2006-06-29'
__version__ = '1.0'


from atexit import register
from itertools import count as icount, ifilter, imap
from os import listdir, remove
from os.path import exists, expanduser, split as psplit
from readline import clear_history, get_current_history_length, \
     get_completer_delims, get_history_item, get_line_buffer, \
     insert_text, parse_and_bind, read_history_file, redisplay, \
     set_completer, set_completer_delims, set_history_length, \
     set_pre_input_hook, write_history_file
from pwd import getpwall
from rlcompleter import Completer
from tempfile import mktemp

import __main__


historyPath = expanduser('~/.pyhistory')
HISTORY_LENGTH = 100




class History:
    def __init__(self):
        self.recall()
        set_history_length(HISTORY_LENGTH)

        parse_and_bind('tab: complete')
        # delims = get_completer_delims()
        delims = ' \t\n`!@#$%^&*()-=+[{]}\\|;:,<>?'
        set_completer_delims(delims)
        set_completer(irlcompleter().complete)


    def __repr__(self):
        """print out current history information"""
        command = get_history_item(get_current_history_length())
        if command == 'history':
            length = get_current_history_length()
            if length > 1:
                return reduce(lambda x, y: '%s\n%s' % (x, y),
                              imap(get_history_item, xrange(1, length)))
            else:
                return ''
        else:
            return '<%s instance>' % __name__


    def __call__(self):
        """print out current history information with line number"""
        length = get_current_history_length()
        if length > 1:
            kount = icount(1).next
            for command in imap(get_history_item, xrange(1, length)):
                print '%s\t%s' % (kount(), command)


    def save(self, filename, pos = None, end = None):
        """write history number from pos to end into filename file"""
        length = get_current_history_length()
        if length > 1:
            if not pos:
                pos = 1
            elif pos >= length - 1:
                pos = length - 1
            elif pos < 1:
                pos = length + pos - 1
            if not end:
                end = length
            elif end >= length:
                end = length
            if end < 0:
                end = length + end
            else:
                end = end + 1

            fp = open(filename, 'w')
            write = fp.write
            if pos < end:
                map(lambda x: write('%s\n' %  x),
                    imap(get_history_item, xrange(pos, end)))
            else:
                write('%s\n' % get_history_item(pos))
            fp.close()


    def clear(self):
        """save the current history and clear it"""
        write_history_file(historyPath)
        clear_history()


    def recall(self, historyPath = historyPath):
        """clear the current history and recall it from saved"""
        clear_history()
        if exists(historyPath):
            read_history_file(historyPath)


    def execute(self, pos, end = None):
        """execute history number from pos to end"""
        length = get_current_history_length()
        if length > 1:
            if pos >= length - 1:
                pos = length - 1
            elif pos < 1:
                pos = length + pos - 1
            if not end:
                end = pos + 1
            elif end >= length:
                end = length
            if end < 0:
                end = length + end
            else:
                end = end + 1

            to_execute = map(get_history_item, xrange(pos, end))

            filename = mktemp()
            fp = open(filename, 'w')
            write = fp.write
            map(lambda x: write('%s\n' % x), to_execute.__iter__())
            fp.close()

            try:
                execfile(filename, __main__.__dict__)
                read_history_file(filename)
                remove(filename)
            except:
                remove(filename)




class irlcompleter(Completer):
    def complete(self, text, state):
        if text == '':
            # you could replace '    ' to \t if you indent via tab
            return ['    ', None][state]
        elif text.count("'") == 1:
            if not state:
                self.file_matches(text, "'")
            try:
                return self.matches[state]
            except IndexError:
                return None
        elif text.count('"') == 1:
            if not state:
                self.file_matches(text, '"')
            try:
                return self.matches[state]
            except IndexError:
                return None
        else:
            return Completer.complete(self, text, state)


    def file_matches(self, text, mark):
        if '~' in text:
            if '/' in text:
                text = '%s%s%s' % (mark, expanduser(
                    text[text.find('~'):text.find('/')]),
                                   text[text.find('/'):])
            else:
                self.user_matches(text, mark)
                return

        text1 = text[1:]
        delim = '/'

        if not text1:
            directory = ''
        elif text1 == '.':
            directory = '.'
        elif text1 == '..':
            directory = '..'
        elif text1 == '/':
            directory = '/'
            delim = ''
        elif text1[-1] == '/':
            directory = text1[:-1]
            delim = text1[len(directory):]
        else:
            directory, partial = psplit(text1)
            delim = text1[len(directory):][:-len(partial)]

        if directory:
            listing = map(lambda x: '%s%s%s%s' % (mark, directory, delim, x),
                          listdir(directory).__iter__())
        else:
            listing = map(lambda x: '%s%s' % (mark, x),
                          listdir('.').__iter__())

        n = len(text)
        self.matches = filter(lambda x: x[:n] == text, listing.__iter__())


    def user_matches(self, text, mark):
        n = len(text)
        self.matches = filter(lambda x: x[:n] == text,
                              imap(lambda x: '%s~%s' % (mark, x[0]),
                                   getpwall().__iter__()))




def save_history(historyPath = historyPath):
    from readline import write_history_file
    write_history_file(historyPath)
register(save_history)


def hook():
    from readline import set_pre_input_hook
    import __main__
    set_pre_input_hook()
    delattr(__main__, 'History')
    delattr(__main__, '__file__')
set_pre_input_hook(hook)
setattr(__main__.__builtins__, 'history', History())

Discussion:

To show an example, I had input as below;
i[tab][tab]m[tab] pwd[return]
pri[tab] pwd.[tab]__do[tab][return]
fp = op[tab]('/[tab][tab]e[tab]/pas[tab]', 'r')[return]
hi[tab][return]


>>> i
i if in int is issubclass
id import input intern isinstance iter

>>> import pwd
>>> print pwd.
pwd.__class__ pwd.__init__ pwd.__str__
pwd.__delattr__ pwd.__name__ pwd.getpwall
pwd.__dict__ pwd.__new__ pwd.getpwnam
pwd.__doc__ pwd.__reduce__ pwd.getpwuid
pwd.__file__ pwd.__reduce_ex__ pwd.struct_passwd
pwd.__getattribute__ pwd.__repr__ pwd.struct_pwent
pwd.__hash__ pwd.__setattr__

>>> fp = open('/
'/bin '/home '/mnt '/sbin
'/boot '/lib '/opt '/tmp
'/dev '/lost+found '/proc '/usr
'/etc '/media '/root '/var

>>> history
import pwd
print pwd.__doc__
fp = open('/etc/passwd', 'r')



Add comment

Number of comments: 9

history view, Sunjoong LEE, 2006/06/26
>>> history
Add comment

history view with number, Sunjoong LEE, 2006/06/26
>>> history()
Add comment

save history to another file, Sunjoong LEE, 2006/06/26
>>> history.save('saved.py')
Add comment

save history number from 1 to 3 into 'saved.py', Sunjoong LEE, 2006/06/26
>>> history.save('saved.py', 1, 3)
Add comment

clear history buffer, Sunjoong LEE, 2006/06/26
>>> history.clear()
Add comment

recall history, Sunjoong LEE, 2006/06/26
>>> history.recall()
Add comment

recall history from another file, Sunjoong LEE, 2006/06/26
>>> history.recall('saved.py')
Add comment

execute history, Sunjoong LEE, 2006/06/28

>>> a = 1
>>> b = a + 1
>>> c = b + 1
>>> print a, b, c
1 2 3
>>> history()
1     a = 1
2     b = a + 1
3     c = b + 1
4     print a, b, c
>>> a = 2
>>> history.run(2, 4)
2 3 4

Add comment

change history.run to history.execute, Sunjoong LEE, 2006/06/28
I has changed the run mathod name to execute.
Add comment



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. IPy Notify

4. Changing return value ...

5. Quantum Superposition

6. Pickle objects under ...

7. Generalized delegates ...

8. Reorder a sequence (uses ...

9. Setting Win32 System ...

10. ObjectMerger




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.