Welcome, guest | Sign In | My Account | Store | Cart

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

Python, 243 lines
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# 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())

To show an example, I had input as below; i[tab][tab]m[tab] pwd[return] pri[tab] pwd.[tab]__do[tab][return] fp = optab[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')

9 comments

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

history view. >>> history

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

history view with number. >>> history()

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

save history to another file. >>> history.save('saved.py')

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

save history number from 1 to 3 into 'saved.py' >>> history.save('saved.py', 1, 3)

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

clear history buffer. >>> history.clear()

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

recall history. >>> history.recall()

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

recall history from another file. >>> history.recall('saved.py')

Sunjoong LEE (author) 15 years, 5 months ago  # | flag

execute history.

>>> 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
Sunjoong LEE (author) 15 years, 5 months ago  # | flag

change history.run to history.execute. I has changed the run mathod name to execute.