Converted to use re instead of regex; version 0.9.0.
This commit is contained in:
parent
9897f0f847
commit
80e57fb21b
|
@ -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
|
||||
-------------------------
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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, '&', '&')
|
||||
s = replace(s, '<', '<')
|
||||
s = replace(s, '>', '>')
|
||||
s = string.replace(s, '&', '&')
|
||||
s = string.replace(s, '<', '<')
|
||||
s = string.replace(s, '>', '>')
|
||||
return s
|
||||
|
||||
def escapeq(s):
|
||||
s = escape(s)
|
||||
s = replace(s, '"', '"')
|
||||
s = string.replace(s, '"', '"')
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue