summaryrefslogtreecommitdiff
path: root/pexpect/tools
diff options
context:
space:
mode:
authornoah <noah@656d521f-e311-0410-88e0-e7920216d269>2006-08-27 07:12:34 +0000
committernoah <noah@656d521f-e311-0410-88e0-e7920216d269>2006-08-27 07:12:34 +0000
commitfce1908d260db219435bddfea8e53f5e6b1b283e (patch)
tree75fd0fcab185f87c45b660606961dd400c40d2ac /pexpect/tools
parentbb025b41abfe691818e7ece087fcaa1e82fcd584 (diff)
downloadpexpect-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.py163
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'"
+"""
+