Converted to use re instead of regex; version 0.9.0.

This commit is contained in:
Guido van Rossum 1997-12-21 07:05:32 +00:00
parent 9897f0f847
commit 80e57fb21b
3 changed files with 52 additions and 55 deletions

View File

@ -2,8 +2,8 @@ FAQ Wizard
----------
Author: Guido van Rossum <guido@python.org>
Version: 0.8.4
Date: 16 December 1997
Version: 0.9.0
Date: 21 December 1997
This is a CGI program that maintains a user-editable FAQ. It uses RCS
@ -22,6 +22,17 @@ faqwiz.py main module, lives in same directory as FAQ entry files
faqconf.py main configuration module
faqcust.py additional local customization module (optional)
What's New?
-----------
Version 0.9.0 uses the re module (Perl style regular expressions) for
all its regular expression needs, instead of the regex and regsub
modules (Emacs style). This affects the syntax for regular
expressions entered by the user as search strings (with "regular
expression" checked), hence the version number jump.
Setup Information
-----------------
@ -76,6 +87,7 @@ file faq01.001.htp,v in the RCS subdirectory. You can now exercise
the other FAQ wizard features (search, index, whole FAQ, what's new,
roulette, and so on).
Maintaining Multiple FAQs
-------------------------

View File

@ -49,7 +49,7 @@ entries marked with * were changed within the last 7 days.)
# Version -- don't change unless you edit faqwiz.py
WIZVERSION = "0.8.4" # FAQ Wizard version
WIZVERSION = "0.9.0" # FAQ Wizard version
# This parameter is normally overwritten with a dynamic value
@ -58,12 +58,12 @@ import os, sys
FAQCGI = os.path.basename(sys.argv[0]) or FAQCGI
del os, sys
# Regular expression to recognize FAQ entry files: group(1) should be
# the section number, group(2) should be the question number. Both
# should be fixed width so simple-minded sorting yields the right
# order.
# Perl (re module) style regular expression to recognize FAQ entry
# files: group(1) should be the section number, group(2) should be the
# question number. Both should be fixed width so simple-minded
# sorting yields the right order.
OKFILENAME = "^faq\([0-9][0-9]\)\.\([0-9][0-9][0-9]\)\.htp$"
OKFILENAME = r"^faq(\d\d)\.(\d\d\d)\.htp$"
# Format to construct a FAQ entry file name

View File

@ -11,7 +11,7 @@ The actual script to place in cgi-bin is faqw.py.
"""
import sys, string, time, os, stat, regex, cgi, faqconf
import sys, string, time, os, stat, re, cgi, faqconf
from faqconf import * # This imports all uppercase names
now = time.time()
@ -32,21 +32,15 @@ class NoSuchFile(FileError):
FileError.__init__(self, file)
self.why = why
def replace(s, old, new):
try:
return string.replace(s, old, new)
except AttributeError:
return string.join(string.split(s, old), new)
def escape(s):
s = replace(s, '&', '&amp;')
s = replace(s, '<', '&lt;')
s = replace(s, '>', '&gt;')
s = string.replace(s, '&', '&amp;')
s = string.replace(s, '<', '&lt;')
s = string.replace(s, '>', '&gt;')
return s
def escapeq(s):
s = escape(s)
s = replace(s, '"', '&quot;')
s = string.replace(s, '"', '&quot;')
return s
def _interpolate(format, args, kw):
@ -73,20 +67,20 @@ translate_prog = None
def translate(text, pre=0):
global translate_prog
if not translate_prog:
url = '\(http\|ftp\|https\)://[^ \t\r\n]*'
email = '\<[-a-zA-Z0-9._]+@[-a-zA-Z0-9._]+'
translate_prog = prog = regex.compile(url + '\|' + email)
translate_prog = prog = re.compile(
r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
else:
prog = translate_prog
i = 0
list = []
while 1:
j = prog.search(text, i)
if j < 0:
m = prog.search(text, i)
if not m:
break
j = m.start()
list.append(escape(text[i:j]))
i = j
url = prog.group(0)
url = m.group(0)
while url[-1] in '();:,.?\'"<>':
url = url[:-1]
i = i + len(url)
@ -103,26 +97,19 @@ def translate(text, pre=0):
list.append(escape(text[i:j]))
return string.join(list, '')
emphasize_prog = None
def emphasize(line):
global emphasize_prog
import regsub
if not emphasize_prog:
pat = '\*\([a-zA-Z]+\)\*'
emphasize_prog = regex.compile(pat)
return regsub.gsub(emphasize_prog, '<I>\\1</I>', line)
return re.sub(r'\*([a-zA-Z]+)\*', r'<I>\1</I>', line)
revparse_prog = None
def revparse(rev):
global revparse_prog
if not revparse_prog:
revparse_prog = regex.compile(
'^\([1-9][0-9]?[0-9]?\)\.\([1-9][0-9]?[0-9]?[0-9]?\)$')
if revparse_prog.match(rev) < 0:
revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1-4})$')
m = revparse_prog.match(rev)
if not m:
return None
[major, minor] = map(string.atoi, revparse_prog.group(1, 2))
[major, minor] = map(string.atoi, m.group(1, 2))
return major, minor
def load_cookies():
@ -315,7 +302,7 @@ class FaqDir:
entryclass = FaqEntry
__okprog = regex.compile(OKFILENAME)
__okprog = re.compile(OKFILENAME)
def __init__(self, dir=os.curdir):
self.__dir = dir
@ -327,17 +314,18 @@ class FaqDir:
self.__files = files = []
okprog = self.__okprog
for file in os.listdir(self.__dir):
if okprog.match(file) >= 0:
if self.__okprog.match(file):
files.append(file)
files.sort()
def good(self, file):
return self.__okprog.match(file) >= 0
return self.__okprog.match(file)
def parse(self, file):
if not self.good(file):
m = self.good(file)
if not m:
return None
sec, num = self.__okprog.group(1, 2)
sec, num = m.group(1, 2)
return string.atoi(sec), string.atoi(num)
def list(self):
@ -426,31 +414,29 @@ class FaqWizard:
self.error("Empty query string!")
return
if self.ui.querytype == 'simple':
for c in '\\.[]?+^$*':
if c in query:
query = replace(query, c, '\\'+c)
query = re.escape(query)
queries = [query]
elif self.ui.querytype in ('anykeywords', 'allkeywords'):
import regsub
words = string.split(regsub.gsub('[^a-zA-Z0-9]+', ' ', query))
words = filter(None, re.split('\W+', query))
if not words:
self.error("No keywords specified!")
return
words = map(lambda w: '\<%s\>' % w, words)
words = map(lambda w: r'\b%s\b' % w, words)
if self.ui.querytype[:3] == 'any':
queries = [string.join(words, '\|')]
queries = [string.join(words, '|')]
else:
# Each of the individual queries must match
queries = words
else:
# Default to regex
# Default to regular expression
queries = [query]
self.prologue(T_SEARCH)
progs = []
for query in queries:
if self.ui.casefold == 'no':
p = regex.compile(query)
p = re.compile(query)
else:
p = regex.compile(query, regex.casefold)
p = re.compile(query, re.IGNORECASE)
progs.append(p)
hits = []
for file in self.dir.list():
@ -459,7 +445,7 @@ class FaqWizard:
except FileError:
constants
for p in progs:
if p.search(entry.title) < 0 and p.search(entry.body) < 0:
if not p.search(entry.title) and not p.search(entry.body):
break
else:
hits.append(file)
@ -777,8 +763,7 @@ class FaqWizard:
file = entry.file
# Normalize line endings in body
if '\r' in self.ui.body:
import regsub
self.ui.body = regsub.gsub('\r\n?', '\n', self.ui.body)
self.ui.body = re.sub('\r\n?', '\n', self.ui.body)
# Normalize whitespace in title
self.ui.title = string.join(string.split(self.ui.title))
# Check that there were any changes