diff options
author | noah <noah@656d521f-e311-0410-88e0-e7920216d269> | 2006-08-27 07:12:34 +0000 |
---|---|---|
committer | noah <noah@656d521f-e311-0410-88e0-e7920216d269> | 2006-08-27 07:12:34 +0000 |
commit | fce1908d260db219435bddfea8e53f5e6b1b283e (patch) | |
tree | 75fd0fcab185f87c45b660606961dd400c40d2ac /pexpect/tools | |
parent | bb025b41abfe691818e7ece087fcaa1e82fcd584 (diff) | |
download | pexpect-fce1908d260db219435bddfea8e53f5e6b1b283e.tar.gz |
Another missing file.
git-svn-id: http://pexpect.svn.sourceforge.net/svnroot/pexpect/trunk@425 656d521f-e311-0410-88e0-e7920216d269
Diffstat (limited to 'pexpect/tools')
-rw-r--r-- | pexpect/tools/pyed.py | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/pexpect/tools/pyed.py b/pexpect/tools/pyed.py new file mode 100644 index 0000000..e58b191 --- /dev/null +++ b/pexpect/tools/pyed.py @@ -0,0 +1,163 @@ +"""This represents a document with methods to allow easy editing. +Think 'sed', only more fun to use. +Example 1: Convert all python-style comments in a file to UPPERCASE. +This operates as a filter on stdin, so this needs a shell pipe. +cat myscript.py | upper_filter.py + import sys, pyed + pe = pyed() + pe.read(sys.stdin) + for pe in pe.match_lines('^\\s*#'): + pe.cur_line = pe.cur_line.upper() + print pe + +Example 2: Edit an Apache2 httpd.conf file to turn on supplemental SSL configuration. + import pyed + pe = pyed() + pe.read("httpd.conf") + pe.first('#Include conf/extra/httpd-ssl.conf') + pe.cur_line = 'Include conf/extra/httpd-ssl.conf' + pe.write("httpd.conf") + +""" + +import re +class pyed (object): + def __init__ (self, new_str=None): + if new_str is not None: + self.lines = new_str.splitlines() + self.cur_line_num = 0 + else: + self.lines = None + # force invalid line number + self.cur_line_num = None + def match_lines (self, pattern, beg=0, end=None): + """This returns a generator that iterates this object + over the lines and yielding when a line matches the pattern. + Note that this generator mutates this object so that + the cur_line is changed to the line matching the pattern. + """ + p = re.compile (pattern) + if end is None: + end = len(self.lines) + for i in xrange (beg,end): + m = p.match(self.lines[i]) + if m is not None: + self.cur_line_num = i + yield self + else: + # force invalid line number + cur_line_num = None + def match_lines_rev (self, pattern, beg=0, end=None): + """This is similar to match_lines, but the order is reversed. + """ + p = re.compile (pattern) + if end is None: + end = len(self.lines) + for i in xrange (end-1,beg-1,-1): + m = p.match(self.lines[i]) + if m is not None: + self.cur_line_num = i + yield self + else: + # force invalid line number + cur_line_num = None + def next (self): + self.cur_line_num = self.cur_line_num + 1 + if self.cur_line_num >= len(self.lines): + self.cur_line_num = len(self.lines) - 1 + return self.cur_line + def prev (self): + self.cur_line_num = self.cur_line_num - 1 + if self.cur_line_num < 0: + self.cur_line_num = 0 + return self.cur_line + def first (self, pattern=None): + if pattern is not None: + try: + return self.match_lines_rev(pattern).next() + except StopIteration, e: + # force invalid line number + self.cur_line_num = None + return None + self.cur_line_num = 0 + return self.cur_line + def last (self, pattern=None): + if pattern is not None: + try: + return self.match_lines_rev(pattern).next() + except StopIteration, e: + # force invalid line number + self.cur_line_num = None + return None + self.cur_line_num = len(self.lines) - 1 + return self.cur_line + def insert (self, s=''): + """This inserts the string as a new line before the current line number. + """ + self.lines.insert(self.cur_line_num, s) + def append (self, s=''): + """Unlike list append, this appends after the current line number, + not at the end of the entire list. + """ + self.cur_line_num = self.cur_line_num + 1 + self.lines.insert(self.cur_line_num, s) + def delete (self): + del self.cur_line + def read (self, file_holder): + """This reads all the lines from a file. The file_holder may be + either a string filename or any object that supports "read()". + All previous lines are lost. + """ + if hasattr(file_holder, 'read') and callable(file_holder.read): + fin = file_holder + else: + fin = open (file_holder, 'rb') + data = fin.read() + self.lines = data.splitlines() + self.cur_line_num = 0 + def write (self, file_holder): + """This writes all the lines to a file. The file_holder may be + either a string filename or any object that supports "read()". + TODO: Make write be atomic using file move instead of overwrite. + """ + if hasattr(file_holder, 'write') and callable(file_holder.write): + fout = file_holder + else: + fout = open (file_holder, 'wb') + for l in self.lines: + fout.write(l) + fout.write('\n') + # the following are for smart properties. + def __str__ (self): + return '\n'.join(self.lines) + def __get_cur_line (self): + self.__cur_line = self.lines[self.cur_line_num] + return self.__cur_line + def __set_cur_line (self, value): + self.__cur_line = value + self.lines[self.cur_line_num] = self.__cur_line + def __del_cur_line (self): + del self.lines[self.cur_line_num] + if self.cur_line_num >= len(self.lines): + self.cur_line_num = len(self.lines) - 1 + cur_line = property (__get_cur_line, __set_cur_line, __del_cur_line) + # lines = property (get_lines, set_lines, del_lines) + +__NOT_USED =""" +import sys +pe = pyed() +pe.read(sys.stdin) +#print "---" +#print list(x.cur_line for x in pe.match_lines_rev('^#')) +#print pe.first('^#') +#print pe.last('^#') +#print "---" +for pe in pe.match_lines('^\\s*#'): + pe.cur_line = pe.cur_line.lower() +pe.last('# comment.*') +pe.cur_line = '# Comment 1' +print pe +if pe.last('asdfasdf') is None: + print "can't find 'asdfasdf'" +""" + |