]> granicus.if.org Git - python/commitdiff
Untabified, for tabnanny.
authorGuido van Rossum <guido@python.org>
Mon, 6 Apr 1998 14:24:36 +0000 (14:24 +0000)
committerGuido van Rossum <guido@python.org>
Mon, 6 Apr 1998 14:24:36 +0000 (14:24 +0000)
Tools/faqwiz/faqwiz.py

index 29712eb7b5819a54a63018011da37ce07c72c8de..f604fd2235fd36cba70b517fcaa126ce3bc160f5 100644 (file)
@@ -12,25 +12,25 @@ The actual script to place in cgi-bin is faqw.py.
 """
 
 import sys, string, time, os, stat, re, cgi, faqconf
-from faqconf import *                  # This imports all uppercase names
+from faqconf import *                   # This imports all uppercase names
 now = time.time()
 
 class FileError:
     def __init__(self, file):
-       self.file = file
+        self.file = file
 
 class InvalidFile(FileError):
     pass
 
 class NoSuchSection(FileError):
     def __init__(self, section):
-       FileError.__init__(self, NEWFILENAME %(section, 1))
-       self.section = section
+        FileError.__init__(self, NEWFILENAME %(section, 1))
+        self.section = section
 
 class NoSuchFile(FileError):
     def __init__(self, file, why=None):
-       FileError.__init__(self, file)
-       self.why = why
+        FileError.__init__(self, file)
+        self.why = why
 
 def escape(s):
     s = string.replace(s, '&', '&amp;')
@@ -45,9 +45,9 @@ def escapeq(s):
 
 def _interpolate(format, args, kw):
     try:
-       quote = kw['_quote']
+        quote = kw['_quote']
     except KeyError:
-       quote = 1
+        quote = 1
     d = (kw,) + args + (faqconf.__dict__,)
     m = MagicDict(d, quote)
     return format % m
@@ -57,9 +57,9 @@ def interpolate(format, *args, **kw):
 
 def emit(format, *args, **kw):
     try:
-       f = kw['_file']
+        f = kw['_file']
     except KeyError:
-       f = sys.stdout
+        f = sys.stdout
     f.write(_interpolate(format, args, kw))
 
 translate_prog = None
@@ -67,32 +67,32 @@ translate_prog = None
 def translate(text, pre=0):
     global translate_prog
     if not translate_prog:
-       translate_prog = prog = re.compile(
-           r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
+        translate_prog = prog = re.compile(
+            r'\b(http|ftp|https)://\S+(\b|/)|\b[-.\w]+@[-.\w]+')
     else:
-       prog = translate_prog
+        prog = translate_prog
     i = 0
     list = []
     while 1:
-       m = prog.search(text, i)
-       if not m:
-           break
-       j = m.start()
-       list.append(escape(text[i:j]))
-       i = j
-       url = m.group(0)
-       while url[-1] in '();:,.?\'"<>':
-           url = url[:-1]
-       i = i + len(url)
-       url = escape(url)
-       if not pre or (pre and PROCESS_PREFORMAT):
-           if ':' in url:
-               repl = '<A HREF="%s">%s</A>' % (url, url)
-           else:
-               repl = '<A HREF="mailto:%s">&lt;%s&gt;</A>' % (url, url)
-       else:
-           repl = url
-       list.append(repl)
+        m = prog.search(text, i)
+        if not m:
+            break
+        j = m.start()
+        list.append(escape(text[i:j]))
+        i = j
+        url = m.group(0)
+        while url[-1] in '();:,.?\'"<>':
+            url = url[:-1]
+        i = i + len(url)
+        url = escape(url)
+        if not pre or (pre and PROCESS_PREFORMAT):
+            if ':' in url:
+                repl = '<A HREF="%s">%s</A>' % (url, url)
+            else:
+                repl = '<A HREF="mailto:%s">&lt;%s&gt;</A>' % (url, url)
+        else:
+            repl = url
+        list.append(repl)
     j = len(text)
     list.append(escape(text[i:j]))
     return string.join(list, '')
@@ -105,43 +105,43 @@ revparse_prog = None
 def revparse(rev):
     global revparse_prog
     if not revparse_prog:
-       revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1-4})$')
+        revparse_prog = re.compile(r'^(\d{1,3})\.(\d{1-4})$')
     m = revparse_prog.match(rev)
     if not m:
-       return None
+        return None
     [major, minor] = map(string.atoi, m.group(1, 2))
     return major, minor
 
 def load_cookies():
     if not os.environ.has_key('HTTP_COOKIE'):
-       return {}
+        return {}
     raw = os.environ['HTTP_COOKIE']
     words = map(string.strip, string.split(raw, ';'))
     cookies = {}
     for word in words:
-       i = string.find(word, '=')
-       if i >= 0:
-           key, value = word[:i], word[i+1:]
-           cookies[key] = value
+        i = string.find(word, '=')
+        if i >= 0:
+            key, value = word[:i], word[i+1:]
+            cookies[key] = value
     return cookies
 
 def load_my_cookie():
     cookies = load_cookies()
     try:
-       value = cookies[COOKIE_NAME]
+        value = cookies[COOKIE_NAME]
     except KeyError:
-       return {}
+        return {}
     import urllib
     value = urllib.unquote(value)
     words = string.split(value, '/')
     while len(words) < 3:
-       words.append('')
+        words.append('')
     author = string.join(words[:-2], '/')
     email = words[-2]
     password = words[-1]
     return {'author': author,
-           'email': email,
-           'password': password}
+            'email': email,
+            'password': password}
 
 def send_my_cookie(ui):
     name = COOKIE_NAME
@@ -156,147 +156,147 @@ def send_my_cookie(ui):
 class MagicDict:
 
     def __init__(self, d, quote):
-       self.__d = d
-       self.__quote = quote
+        self.__d = d
+        self.__quote = quote
 
     def __getitem__(self, key):
-       for d in self.__d:
-           try:
-               value = d[key]
-               if value:
-                   value = str(value)
-                   if self.__quote:
-                       value = escapeq(value)
-                   return value
-           except KeyError:
-               pass
-       return ''
+        for d in self.__d:
+            try:
+                value = d[key]
+                if value:
+                    value = str(value)
+                    if self.__quote:
+                        value = escapeq(value)
+                    return value
+            except KeyError:
+                pass
+        return ''
 
 class UserInput:
 
     def __init__(self):
-       self.__form = cgi.FieldStorage()
+        self.__form = cgi.FieldStorage()
 
     def __getattr__(self, name):
-       if name[0] == '_':
-           raise AttributeError
-       try:
-           value = self.__form[name].value
-       except (TypeError, KeyError):
-           value = ''
-       else:
-           value = string.strip(value)
-       setattr(self, name, value)
-       return value
+        if name[0] == '_':
+            raise AttributeError
+        try:
+            value = self.__form[name].value
+        except (TypeError, KeyError):
+            value = ''
+        else:
+            value = string.strip(value)
+        setattr(self, name, value)
+        return value
 
     def __getitem__(self, key):
-       return getattr(self, key)
+        return getattr(self, key)
 
 class FaqEntry:
 
     def __init__(self, fp, file, sec_num):
-       self.file = file
-       self.sec, self.num = sec_num
-       if fp:
-           import rfc822
-           self.__headers = rfc822.Message(fp)
-           self.body = string.strip(fp.read())
-       else:
-           self.__headers = {'title': "%d.%d. " % sec_num}
-           self.body = ''
+        self.file = file
+        self.sec, self.num = sec_num
+        if fp:
+            import rfc822
+            self.__headers = rfc822.Message(fp)
+            self.body = string.strip(fp.read())
+        else:
+            self.__headers = {'title': "%d.%d. " % sec_num}
+            self.body = ''
 
     def __getattr__(self, name):
-       if name[0] == '_':
-           raise AttributeError
-       key = string.join(string.split(name, '_'), '-')
-       try:
-           value = self.__headers[key]
-       except KeyError:
-           value = ''
-       setattr(self, name, value)
-       return value
+        if name[0] == '_':
+            raise AttributeError
+        key = string.join(string.split(name, '_'), '-')
+        try:
+            value = self.__headers[key]
+        except KeyError:
+            value = ''
+        setattr(self, name, value)
+        return value
 
     def __getitem__(self, key):
-       return getattr(self, key)
+        return getattr(self, key)
 
     def load_version(self):
-       command = interpolate(SH_RLOG_H, self)
-       p = os.popen(command)
-       version = ''
-       while 1:
-           line = p.readline()
-           if not line:
-               break
-           if line[:5] == 'head:':
-               version = string.strip(line[5:])
-       p.close()
-       self.version = version
+        command = interpolate(SH_RLOG_H, self)
+        p = os.popen(command)
+        version = ''
+        while 1:
+            line = p.readline()
+            if not line:
+                break
+            if line[:5] == 'head:':
+                version = string.strip(line[5:])
+        p.close()
+        self.version = version
 
     def getmtime(self):
-       if not self.last_changed_date:
-           return 0
-       try:
-           return os.stat(self.file)[stat.ST_MTIME]
-       except os.error:
-           return 0
+        if not self.last_changed_date:
+            return 0
+        try:
+            return os.stat(self.file)[stat.ST_MTIME]
+        except os.error:
+            return 0
 
     def emit_marks(self):
-       mtime = self.getmtime()
-       if mtime >= now - DT_VERY_RECENT:
-           emit(MARK_VERY_RECENT, self)
-       elif mtime >= now - DT_RECENT:
-           emit(MARK_RECENT, self)
+        mtime = self.getmtime()
+        if mtime >= now - DT_VERY_RECENT:
+            emit(MARK_VERY_RECENT, self)
+        elif mtime >= now - DT_RECENT:
+            emit(MARK_RECENT, self)
 
     def show(self, edit=1):
-       emit(ENTRY_HEADER1, self)
-       self.emit_marks()
-       emit(ENTRY_HEADER2, self)
-       pre = 0
-       raw = 0
-       for line in string.split(self.body, '\n'):
-           # Allow the user to insert raw html into a FAQ answer
-           # (Skip Montanaro, with changes by Guido)
-           tag = string.lower(string.rstrip(line))
-           if tag == '<html>':
-               raw = 1
-               continue
-           if tag == '</html>':
-               raw = 0
-               continue
-           if raw:
-               print line
-               continue
-           if not string.strip(line):
-               if pre:
-                   print '</PRE>'
-                   pre = 0
-               else:
-                   print '<P>'
-           else:
-               if line[0] not in string.whitespace:
-                   if pre:
-                       print '</PRE>'
-                       pre = 0
-               else:
-                   if not pre:
-                       print '<PRE>'
-                       pre = 1
-               if '/' in line or '@' in line:
-                   line = translate(line, pre)
-               elif '<' in line or '&' in line:
-                   line = escape(line)
-               if not pre and '*' in line:
-                   line = emphasize(line)
-               print line
-       if pre:
-           print '</PRE>'
-           pre = 0
-       if edit:
-           print '<P>'
-           emit(ENTRY_FOOTER, self)
-           if self.last_changed_date:
-               emit(ENTRY_LOGINFO, self)
-       print '<P>'
+        emit(ENTRY_HEADER1, self)
+        self.emit_marks()
+        emit(ENTRY_HEADER2, self)
+        pre = 0
+        raw = 0
+        for line in string.split(self.body, '\n'):
+            # Allow the user to insert raw html into a FAQ answer
+            # (Skip Montanaro, with changes by Guido)
+            tag = string.lower(string.rstrip(line))
+            if tag == '<html>':
+                raw = 1
+                continue
+            if tag == '</html>':
+                raw = 0
+                continue
+            if raw:
+                print line
+                continue
+            if not string.strip(line):
+                if pre:
+                    print '</PRE>'
+                    pre = 0
+                else:
+                    print '<P>'
+            else:
+                if line[0] not in string.whitespace:
+                    if pre:
+                        print '</PRE>'
+                        pre = 0
+                else:
+                    if not pre:
+                        print '<PRE>'
+                        pre = 1
+                if '/' in line or '@' in line:
+                    line = translate(line, pre)
+                elif '<' in line or '&' in line:
+                    line = escape(line)
+                if not pre and '*' in line:
+                    line = emphasize(line)
+                print line
+        if pre:
+            print '</PRE>'
+            pre = 0
+        if edit:
+            print '<P>'
+            emit(ENTRY_FOOTER, self)
+            if self.last_changed_date:
+                emit(ENTRY_LOGINFO, self)
+        print '<P>'
 
 class FaqDir:
 
@@ -305,517 +305,517 @@ class FaqDir:
     __okprog = re.compile(OKFILENAME)
 
     def __init__(self, dir=os.curdir):
-       self.__dir = dir
-       self.__files = None
+        self.__dir = dir
+        self.__files = None
 
     def __fill(self):
-       if self.__files is not None:
-           return
-       self.__files = files = []
-       okprog = self.__okprog
-       for file in os.listdir(self.__dir):
-           if self.__okprog.match(file):
-               files.append(file)
-       files.sort()
+        if self.__files is not None:
+            return
+        self.__files = files = []
+        okprog = self.__okprog
+        for file in os.listdir(self.__dir):
+            if self.__okprog.match(file):
+                files.append(file)
+        files.sort()
 
     def good(self, file):
-       return self.__okprog.match(file)
+        return self.__okprog.match(file)
 
     def parse(self, file):
-       m = self.good(file)
-       if not m:
-           return None
-       sec, num = m.group(1, 2)
-       return string.atoi(sec), string.atoi(num)
+        m = self.good(file)
+        if not m:
+            return None
+        sec, num = m.group(1, 2)
+        return string.atoi(sec), string.atoi(num)
 
     def list(self):
-       # XXX Caller shouldn't modify result
-       self.__fill()
-       return self.__files
+        # XXX Caller shouldn't modify result
+        self.__fill()
+        return self.__files
 
     def open(self, file):
-       sec_num = self.parse(file)
-       if not sec_num:
-           raise InvalidFile(file)
-       try:
-           fp = open(file)
-       except IOError, msg:
-           raise NoSuchFile(file, msg)
-       try:
-           return self.entryclass(fp, file, sec_num)
-       finally:
-           fp.close()
+        sec_num = self.parse(file)
+        if not sec_num:
+            raise InvalidFile(file)
+        try:
+            fp = open(file)
+        except IOError, msg:
+            raise NoSuchFile(file, msg)
+        try:
+            return self.entryclass(fp, file, sec_num)
+        finally:
+            fp.close()
 
     def show(self, file, edit=1):
-       self.open(file).show(edit=edit)
+        self.open(file).show(edit=edit)
 
     def new(self, section):
-       if not SECTION_TITLES.has_key(section):
-           raise NoSuchSection(section)
-       maxnum = 0
-       for file in self.list():
-           sec, num = self.parse(file)
-           if sec == section:
-               maxnum = max(maxnum, num)
-       sec_num = (section, maxnum+1)
-       file = NEWFILENAME % sec_num
-       return self.entryclass(None, file, sec_num)
+        if not SECTION_TITLES.has_key(section):
+            raise NoSuchSection(section)
+        maxnum = 0
+        for file in self.list():
+            sec, num = self.parse(file)
+            if sec == section:
+                maxnum = max(maxnum, num)
+        sec_num = (section, maxnum+1)
+        file = NEWFILENAME % sec_num
+        return self.entryclass(None, file, sec_num)
 
 class FaqWizard:
 
     def __init__(self):
-       self.ui = UserInput()
-       self.dir = FaqDir()
+        self.ui = UserInput()
+        self.dir = FaqDir()
 
     def go(self):
-       print 'Content-type: text/html'
-       req = self.ui.req or 'home'
-       mname = 'do_%s' % req
-       try:
-           meth = getattr(self, mname)
-       except AttributeError:
-           self.error("Bad request type %s." % `req`)
-       else:
-           try:
-               meth()
-           except InvalidFile, exc:
-               self.error("Invalid entry file name %s" % exc.file)
-           except NoSuchFile, exc:
-               self.error("No entry with file name %s" % exc.file)
-           except NoSuchSection, exc:
-               self.error("No section number %s" % exc.section)
-       self.epilogue()
+        print 'Content-type: text/html'
+        req = self.ui.req or 'home'
+        mname = 'do_%s' % req
+        try:
+            meth = getattr(self, mname)
+        except AttributeError:
+            self.error("Bad request type %s." % `req`)
+        else:
+            try:
+                meth()
+            except InvalidFile, exc:
+                self.error("Invalid entry file name %s" % exc.file)
+            except NoSuchFile, exc:
+                self.error("No entry with file name %s" % exc.file)
+            except NoSuchSection, exc:
+                self.error("No section number %s" % exc.section)
+        self.epilogue()
 
     def error(self, message, **kw):
-       self.prologue(T_ERROR)
-       emit(message, kw)
+        self.prologue(T_ERROR)
+        emit(message, kw)
 
     def prologue(self, title, entry=None, **kw):
-       emit(PROLOGUE, entry, kwdict=kw, title=escape(title))
+        emit(PROLOGUE, entry, kwdict=kw, title=escape(title))
 
     def epilogue(self):
-       emit(EPILOGUE)
+        emit(EPILOGUE)
 
     def do_home(self):
-       self.prologue(T_HOME)
-       emit(HOME)
+        self.prologue(T_HOME)
+        emit(HOME)
 
     def do_debug(self):
-       self.prologue("FAQ Wizard Debugging")
-       form = cgi.FieldStorage()
-       cgi.print_form(form)
+        self.prologue("FAQ Wizard Debugging")
+        form = cgi.FieldStorage()
+        cgi.print_form(form)
         cgi.print_environ(os.environ)
-       cgi.print_directory()
-       cgi.print_arguments()
+        cgi.print_directory()
+        cgi.print_arguments()
 
     def do_search(self):
-       query = self.ui.query
-       if not query:
-           self.error("Empty query string!")
-           return
-       if self.ui.querytype == 'simple':
-           query = re.escape(query)
-           queries = [query]
-       elif self.ui.querytype in ('anykeywords', 'allkeywords'):
-           words = filter(None, re.split('\W+', query))
-           if not words:
-               self.error("No keywords specified!")
-               return
-           words = map(lambda w: r'\b%s\b' % w, words)
-           if self.ui.querytype[:3] == 'any':
-               queries = [string.join(words, '|')]
-           else:
-               # Each of the individual queries must match
-               queries = words
-       else:
-           # Default to regular expression
-           queries = [query]
-       self.prologue(T_SEARCH)
-       progs = []
-       for query in queries:
-           if self.ui.casefold == 'no':
-               p = re.compile(query)
-           else:
-               p = re.compile(query, re.IGNORECASE)
-           progs.append(p)
-       hits = []
-       for file in self.dir.list():
-           try:
-               entry = self.dir.open(file)
-           except FileError:
-               constants
-           for p in progs:
-               if not p.search(entry.title) and not p.search(entry.body):
-                   break
-           else:
-               hits.append(file)
-       if not hits:
-           emit(NO_HITS, self.ui, count=0)
-       elif len(hits) <= MAXHITS:
-           if len(hits) == 1:
-               emit(ONE_HIT, count=1)
-           else:
-               emit(FEW_HITS, count=len(hits))
-           self.format_all(hits, headers=0)
-       else:
-           emit(MANY_HITS, count=len(hits))
-           self.format_index(hits)
+        query = self.ui.query
+        if not query:
+            self.error("Empty query string!")
+            return
+        if self.ui.querytype == 'simple':
+            query = re.escape(query)
+            queries = [query]
+        elif self.ui.querytype in ('anykeywords', 'allkeywords'):
+            words = filter(None, re.split('\W+', query))
+            if not words:
+                self.error("No keywords specified!")
+                return
+            words = map(lambda w: r'\b%s\b' % w, words)
+            if self.ui.querytype[:3] == 'any':
+                queries = [string.join(words, '|')]
+            else:
+                # Each of the individual queries must match
+                queries = words
+        else:
+            # Default to regular expression
+            queries = [query]
+        self.prologue(T_SEARCH)
+        progs = []
+        for query in queries:
+            if self.ui.casefold == 'no':
+                p = re.compile(query)
+            else:
+                p = re.compile(query, re.IGNORECASE)
+            progs.append(p)
+        hits = []
+        for file in self.dir.list():
+            try:
+                entry = self.dir.open(file)
+            except FileError:
+                constants
+            for p in progs:
+                if not p.search(entry.title) and not p.search(entry.body):
+                    break
+            else:
+                hits.append(file)
+        if not hits:
+            emit(NO_HITS, self.ui, count=0)
+        elif len(hits) <= MAXHITS:
+            if len(hits) == 1:
+                emit(ONE_HIT, count=1)
+            else:
+                emit(FEW_HITS, count=len(hits))
+            self.format_all(hits, headers=0)
+        else:
+            emit(MANY_HITS, count=len(hits))
+            self.format_index(hits)
 
     def do_all(self):
-       self.prologue(T_ALL)
-       files = self.dir.list()
-       self.last_changed(files)
-       self.format_index(files, localrefs=1)
-       self.format_all(files)
+        self.prologue(T_ALL)
+        files = self.dir.list()
+        self.last_changed(files)
+        self.format_index(files, localrefs=1)
+        self.format_all(files)
 
     def do_compat(self):
-       files = self.dir.list()
-       emit(COMPAT)
-       self.last_changed(files)
-       self.format_index(files, localrefs=1)
-       self.format_all(files, edit=0)
-       sys.exit(0)                     # XXX Hack to suppress epilogue
+        files = self.dir.list()
+        emit(COMPAT)
+        self.last_changed(files)
+        self.format_index(files, localrefs=1)
+        self.format_all(files, edit=0)
+        sys.exit(0)                     # XXX Hack to suppress epilogue
 
     def last_changed(self, files):
-       latest = 0
-       for file in files:
-           entry = self.dir.open(file)
-           if entry:
-               mtime = mtime = entry.getmtime()
-               if mtime > latest:
-                   latest = mtime
-       print time.strftime(LAST_CHANGED, time.localtime(latest))
-       emit(EXPLAIN_MARKS)
+        latest = 0
+        for file in files:
+            entry = self.dir.open(file)
+            if entry:
+                mtime = mtime = entry.getmtime()
+                if mtime > latest:
+                    latest = mtime
+        print time.strftime(LAST_CHANGED, time.localtime(latest))
+        emit(EXPLAIN_MARKS)
 
     def format_all(self, files, edit=1, headers=1):
-       sec = 0
-       for file in files:
-           try:
-               entry = self.dir.open(file)
-           except NoSuchFile:
-               continue
-           if headers and entry.sec != sec:
-               sec = entry.sec
-               try:
-                   title = SECTION_TITLES[sec]
-               except KeyError:
-                   title = "Untitled"
-               emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n",
-                    sec=sec, title=title)
-           entry.show(edit=edit)
+        sec = 0
+        for file in files:
+            try:
+                entry = self.dir.open(file)
+            except NoSuchFile:
+                continue
+            if headers and entry.sec != sec:
+                sec = entry.sec
+                try:
+                    title = SECTION_TITLES[sec]
+                except KeyError:
+                    title = "Untitled"
+                emit("\n<HR>\n<H1>%(sec)s. %(title)s</H1>\n",
+                     sec=sec, title=title)
+            entry.show(edit=edit)
 
     def do_index(self):
-       self.prologue(T_INDEX)
-       files = self.dir.list()
-       self.last_changed(files)
-       self.format_index(files, add=1)
+        self.prologue(T_INDEX)
+        files = self.dir.list()
+        self.last_changed(files)
+        self.format_index(files, add=1)
 
     def format_index(self, files, add=0, localrefs=0):
-       sec = 0
-       for file in files:
-           try:
-               entry = self.dir.open(file)
-           except NoSuchFile:
-               continue
-           if entry.sec != sec:
-               if sec:
-                   if add:
-                       emit(INDEX_ADDSECTION, sec=sec)
-                   emit(INDEX_ENDSECTION, sec=sec)
-               sec = entry.sec
-               try:
-                   title = SECTION_TITLES[sec]
-               except KeyError:
-                   title = "Untitled"
-               emit(INDEX_SECTION, sec=sec, title=title)
-           if localrefs:
-               emit(LOCAL_ENTRY, entry)
-           else:
-               emit(INDEX_ENTRY, entry)
-           entry.emit_marks()
-       if sec:
-           if add:
-               emit(INDEX_ADDSECTION, sec=sec)
-           emit(INDEX_ENDSECTION, sec=sec)
+        sec = 0
+        for file in files:
+            try:
+                entry = self.dir.open(file)
+            except NoSuchFile:
+                continue
+            if entry.sec != sec:
+                if sec:
+                    if add:
+                        emit(INDEX_ADDSECTION, sec=sec)
+                    emit(INDEX_ENDSECTION, sec=sec)
+                sec = entry.sec
+                try:
+                    title = SECTION_TITLES[sec]
+                except KeyError:
+                    title = "Untitled"
+                emit(INDEX_SECTION, sec=sec, title=title)
+            if localrefs:
+                emit(LOCAL_ENTRY, entry)
+            else:
+                emit(INDEX_ENTRY, entry)
+            entry.emit_marks()
+        if sec:
+            if add:
+                emit(INDEX_ADDSECTION, sec=sec)
+            emit(INDEX_ENDSECTION, sec=sec)
 
     def do_recent(self):
-       if not self.ui.days:
-           days = 1
-       else:
-           days = string.atof(self.ui.days)
-       try:
-           cutoff = now - days * 24 * 3600
-       except OverflowError:
-           cutoff = 0
-       list = []
-       for file in self.dir.list():
-           entry = self.dir.open(file)
-           if not entry:
-               continue
-           mtime = entry.getmtime()
-           if mtime >= cutoff:
-               list.append((mtime, file))
-       list.sort()
-       list.reverse()
-       self.prologue(T_RECENT)
-       if days <= 1:
-           period = "%.2g hours" % (days*24)
-       else:
-           period = "%.6g days" % days
-       if not list:
-           emit(NO_RECENT, period=period)
-       elif len(list) == 1:
-           emit(ONE_RECENT, period=period)
-       else:
-           emit(SOME_RECENT, period=period, count=len(list))
-       self.format_all(map(lambda (mtime, file): file, list), headers=0)
-       emit(TAIL_RECENT)
+        if not self.ui.days:
+            days = 1
+        else:
+            days = string.atof(self.ui.days)
+        try:
+            cutoff = now - days * 24 * 3600
+        except OverflowError:
+            cutoff = 0
+        list = []
+        for file in self.dir.list():
+            entry = self.dir.open(file)
+            if not entry:
+                continue
+            mtime = entry.getmtime()
+            if mtime >= cutoff:
+                list.append((mtime, file))
+        list.sort()
+        list.reverse()
+        self.prologue(T_RECENT)
+        if days <= 1:
+            period = "%.2g hours" % (days*24)
+        else:
+            period = "%.6g days" % days
+        if not list:
+            emit(NO_RECENT, period=period)
+        elif len(list) == 1:
+            emit(ONE_RECENT, period=period)
+        else:
+            emit(SOME_RECENT, period=period, count=len(list))
+        self.format_all(map(lambda (mtime, file): file, list), headers=0)
+        emit(TAIL_RECENT)
 
     def do_roulette(self):
-       import whrandom
-       files = self.dir.list()
-       if not files: 
-           self.error("No entries.")
-           return
-       file = whrandom.choice(files)
-       self.prologue(T_ROULETTE)
-       emit(ROULETTE)
-       self.dir.show(file)
+        import whrandom
+        files = self.dir.list()
+        if not files: 
+            self.error("No entries.")
+            return
+        file = whrandom.choice(files)
+        self.prologue(T_ROULETTE)
+        emit(ROULETTE)
+        self.dir.show(file)
 
     def do_help(self):
-       self.prologue(T_HELP)
-       emit(HELP)
+        self.prologue(T_HELP)
+        emit(HELP)
 
     def do_show(self):
-       entry = self.dir.open(self.ui.file)
-       self.prologue(T_SHOW)
-       entry.show()
+        entry = self.dir.open(self.ui.file)
+        self.prologue(T_SHOW)
+        entry.show()
 
     def do_add(self):
-       self.prologue(T_ADD)
-       emit(ADD_HEAD)
-       sections = SECTION_TITLES.items()
-       sections.sort()
-       for section, title in sections:
-           emit(ADD_SECTION, section=section, title=title)
-       emit(ADD_TAIL)
+        self.prologue(T_ADD)
+        emit(ADD_HEAD)
+        sections = SECTION_TITLES.items()
+        sections.sort()
+        for section, title in sections:
+            emit(ADD_SECTION, section=section, title=title)
+        emit(ADD_TAIL)
 
     def do_delete(self):
-       self.prologue(T_DELETE)
-       emit(DELETE)
+        self.prologue(T_DELETE)
+        emit(DELETE)
 
     def do_log(self):
-       entry = self.dir.open(self.ui.file)
-       self.prologue(T_LOG, entry)
-       emit(LOG, entry)
-       self.rlog(interpolate(SH_RLOG, entry), entry)
+        entry = self.dir.open(self.ui.file)
+        self.prologue(T_LOG, entry)
+        emit(LOG, entry)
+        self.rlog(interpolate(SH_RLOG, entry), entry)
 
     def rlog(self, command, entry=None):
-       output = os.popen(command).read()
-       sys.stdout.write('<PRE>')
-       athead = 0
-       lines = string.split(output, '\n')
-       while lines and not lines[-1]:
-           del lines[-1]
-       if lines:
-           line = lines[-1]
-           if line[:1] == '=' and len(line) >= 40 and \
-              line == line[0]*len(line):
-               del lines[-1]
-       headrev = None
-       for line in lines:
-           if entry and athead and line[:9] == 'revision ':
-               rev = string.strip(line[9:])
-               mami = revparse(rev)
-               if not mami:
-                   print line
-               else:
-                   emit(REVISIONLINK, entry, rev=rev, line=line)
-                   if mami[1] > 1:
-                       prev = "%d.%d" % (mami[0], mami[1]-1)
-                       emit(DIFFLINK, entry, prev=prev, rev=rev)
-                   if headrev:
-                       emit(DIFFLINK, entry, prev=rev, rev=headrev)
-                   else:
-                       headrev = rev
-                   print
-               athead = 0
-           else:
-               athead = 0
-               if line[:1] == '-' and len(line) >= 20 and \
-                  line == len(line) * line[0]:
-                   athead = 1
-                   sys.stdout.write('<HR>')
-               else:
-                   print line
-       print '</PRE>'
+        output = os.popen(command).read()
+        sys.stdout.write('<PRE>')
+        athead = 0
+        lines = string.split(output, '\n')
+        while lines and not lines[-1]:
+            del lines[-1]
+        if lines:
+            line = lines[-1]
+            if line[:1] == '=' and len(line) >= 40 and \
+               line == line[0]*len(line):
+                del lines[-1]
+        headrev = None
+        for line in lines:
+            if entry and athead and line[:9] == 'revision ':
+                rev = string.strip(line[9:])
+                mami = revparse(rev)
+                if not mami:
+                    print line
+                else:
+                    emit(REVISIONLINK, entry, rev=rev, line=line)
+                    if mami[1] > 1:
+                        prev = "%d.%d" % (mami[0], mami[1]-1)
+                        emit(DIFFLINK, entry, prev=prev, rev=rev)
+                    if headrev:
+                        emit(DIFFLINK, entry, prev=rev, rev=headrev)
+                    else:
+                        headrev = rev
+                    print
+                athead = 0
+            else:
+                athead = 0
+                if line[:1] == '-' and len(line) >= 20 and \
+                   line == len(line) * line[0]:
+                    athead = 1
+                    sys.stdout.write('<HR>')
+                else:
+                    print line
+        print '</PRE>'
 
     def do_revision(self):
-       entry = self.dir.open(self.ui.file)
-       rev = self.ui.rev
-       mami = revparse(rev)
-       if not mami:
-           self.error("Invalid revision number: %s." % `rev`)
-       self.prologue(T_REVISION, entry)
-       self.shell(interpolate(SH_REVISION, entry, rev=rev))
+        entry = self.dir.open(self.ui.file)
+        rev = self.ui.rev
+        mami = revparse(rev)
+        if not mami:
+            self.error("Invalid revision number: %s." % `rev`)
+        self.prologue(T_REVISION, entry)
+        self.shell(interpolate(SH_REVISION, entry, rev=rev))
 
     def do_diff(self):
-       entry = self.dir.open(self.ui.file)
-       prev = self.ui.prev
-       rev = self.ui.rev
-       mami = revparse(rev)
-       if not mami:
-           self.error("Invalid revision number: %s." % `rev`)
-       if prev:
-           if not revparse(prev):
-               self.error("Invalid previous revision number: %s." % `prev`)
-       else:
-           prev = '%d.%d' % (mami[0], mami[1])
-       self.prologue(T_DIFF, entry)
-       self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev))
+        entry = self.dir.open(self.ui.file)
+        prev = self.ui.prev
+        rev = self.ui.rev
+        mami = revparse(rev)
+        if not mami:
+            self.error("Invalid revision number: %s." % `rev`)
+        if prev:
+            if not revparse(prev):
+                self.error("Invalid previous revision number: %s." % `prev`)
+        else:
+            prev = '%d.%d' % (mami[0], mami[1])
+        self.prologue(T_DIFF, entry)
+        self.shell(interpolate(SH_RDIFF, entry, rev=rev, prev=prev))
 
     def shell(self, command):
-       output = os.popen(command).read()
-       sys.stdout.write('<PRE>')
-       print escape(output)
-       print '</PRE>'
+        output = os.popen(command).read()
+        sys.stdout.write('<PRE>')
+        print escape(output)
+        print '</PRE>'
 
     def do_new(self):
-       entry = self.dir.new(section=string.atoi(self.ui.section))
-       entry.version = '*new*'
-       self.prologue(T_EDIT)
-       emit(EDITHEAD)
-       emit(EDITFORM1, entry, editversion=entry.version)
-       emit(EDITFORM2, entry, load_my_cookie())
-       emit(EDITFORM3)
-       entry.show(edit=0)
+        entry = self.dir.new(section=string.atoi(self.ui.section))
+        entry.version = '*new*'
+        self.prologue(T_EDIT)
+        emit(EDITHEAD)
+        emit(EDITFORM1, entry, editversion=entry.version)
+        emit(EDITFORM2, entry, load_my_cookie())
+        emit(EDITFORM3)
+        entry.show(edit=0)
 
     def do_edit(self):
-       entry = self.dir.open(self.ui.file)
-       entry.load_version()
-       self.prologue(T_EDIT)
-       emit(EDITHEAD)
-       emit(EDITFORM1, entry, editversion=entry.version)
-       emit(EDITFORM2, entry, load_my_cookie())
-       emit(EDITFORM3)
-       entry.show(edit=0)
+        entry = self.dir.open(self.ui.file)
+        entry.load_version()
+        self.prologue(T_EDIT)
+        emit(EDITHEAD)
+        emit(EDITFORM1, entry, editversion=entry.version)
+        emit(EDITFORM2, entry, load_my_cookie())
+        emit(EDITFORM3)
+        entry.show(edit=0)
 
     def do_review(self):
-       send_my_cookie(self.ui)
-       if self.ui.editversion == '*new*':
-           sec, num = self.dir.parse(self.ui.file)
-           entry = self.dir.new(section=sec)
-           entry.version = "*new*"
-           if entry.file != self.ui.file:
-               self.error("Commit version conflict!")
-               emit(NEWCONFLICT, self.ui, sec=sec, num=num)
-               return
-       else:
-           entry = self.dir.open(self.ui.file)
-           entry.load_version()
-       # Check that the FAQ entry number didn't change
-       if string.split(self.ui.title)[:1] != string.split(entry.title)[:1]:
-           self.error("Don't change the entry number please!")
-           return
-       # Check that the edited version is the current version
-       if entry.version != self.ui.editversion:
-           self.error("Commit version conflict!")
-           emit(VERSIONCONFLICT, entry, self.ui)
-           return
-       commit_ok = ((not PASSWORD
-                     or self.ui.password == PASSWORD) 
-                    and self.ui.author
-                    and '@' in self.ui.email
-                    and self.ui.log)
-       if self.ui.commit:
-           if not commit_ok:
-               self.cantcommit()
-           else:
-               self.commit(entry)
-           return
-       self.prologue(T_REVIEW)
-       emit(REVIEWHEAD)
-       entry.body = self.ui.body
-       entry.title = self.ui.title
-       entry.show(edit=0)
-       emit(EDITFORM1, self.ui, entry)
-       if commit_ok:
-           emit(COMMIT)
-       else:
-           emit(NOCOMMIT)
-       emit(EDITFORM2, self.ui, entry, load_my_cookie())
-       emit(EDITFORM3)
+        send_my_cookie(self.ui)
+        if self.ui.editversion == '*new*':
+            sec, num = self.dir.parse(self.ui.file)
+            entry = self.dir.new(section=sec)
+            entry.version = "*new*"
+            if entry.file != self.ui.file:
+                self.error("Commit version conflict!")
+                emit(NEWCONFLICT, self.ui, sec=sec, num=num)
+                return
+        else:
+            entry = self.dir.open(self.ui.file)
+            entry.load_version()
+        # Check that the FAQ entry number didn't change
+        if string.split(self.ui.title)[:1] != string.split(entry.title)[:1]:
+            self.error("Don't change the entry number please!")
+            return
+        # Check that the edited version is the current version
+        if entry.version != self.ui.editversion:
+            self.error("Commit version conflict!")
+            emit(VERSIONCONFLICT, entry, self.ui)
+            return
+        commit_ok = ((not PASSWORD
+                      or self.ui.password == PASSWORD) 
+                     and self.ui.author
+                     and '@' in self.ui.email
+                     and self.ui.log)
+        if self.ui.commit:
+            if not commit_ok:
+                self.cantcommit()
+            else:
+                self.commit(entry)
+            return
+        self.prologue(T_REVIEW)
+        emit(REVIEWHEAD)
+        entry.body = self.ui.body
+        entry.title = self.ui.title
+        entry.show(edit=0)
+        emit(EDITFORM1, self.ui, entry)
+        if commit_ok:
+            emit(COMMIT)
+        else:
+            emit(NOCOMMIT)
+        emit(EDITFORM2, self.ui, entry, load_my_cookie())
+        emit(EDITFORM3)
 
     def cantcommit(self):
-       self.prologue(T_CANTCOMMIT)
-       print CANTCOMMIT_HEAD
-       if not self.ui.passwd:
-           emit(NEED_PASSWD)
-       if not self.ui.log:
-           emit(NEED_LOG)
-       if not self.ui.author:
-           emit(NEED_AUTHOR)
-       if not self.ui.email:
-           emit(NEED_EMAIL)
-       print CANTCOMMIT_TAIL
+        self.prologue(T_CANTCOMMIT)
+        print CANTCOMMIT_HEAD
+        if not self.ui.passwd:
+            emit(NEED_PASSWD)
+        if not self.ui.log:
+            emit(NEED_LOG)
+        if not self.ui.author:
+            emit(NEED_AUTHOR)
+        if not self.ui.email:
+            emit(NEED_EMAIL)
+        print CANTCOMMIT_TAIL
 
     def commit(self, entry):
-       file = entry.file
-       # Normalize line endings in body
-       if '\r' in 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
-       if self.ui.body == entry.body and self.ui.title == entry.title:
-           self.error("You didn't make any changes!")
-           return
-       # XXX Should lock here
-       try:
-           os.unlink(file)
-       except os.error:
-           pass
-       try:
-           f = open(file, 'w')
-       except IOError, why:
-           self.error(CANTWRITE, file=file, why=why)
-           return
-       date = time.ctime(now)
-       emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0)
-       f.write('\n')
-       f.write(self.ui.body)
-       f.write('\n')
-       f.close()
-
-       import tempfile
-       tfn = tempfile.mktemp()
-       f = open(tfn, 'w')
-       emit(LOGHEADER, self.ui, os.environ, date=date, _file=f)
-       f.close()
-
-       command = interpolate(
-           SH_LOCK + '\n' + SH_CHECKIN,
-           file=file, tfn=tfn)
-
-       p = os.popen(command)
-       output = p.read()
-       sts = p.close()
-       # XXX Should unlock here
-       if not sts:
-           self.prologue(T_COMMITTED)
-           emit(COMMITTED)
-       else:
-           self.error(T_COMMITFAILED)
-           emit(COMMITFAILED, sts=sts)
-       print '<PRE>%s</PRE>' % escape(output)
-
-       try:
-           os.unlink(tfn)
-       except os.error:
-           pass
-
-       entry = self.dir.open(file)
-       entry.show()
+        file = entry.file
+        # Normalize line endings in body
+        if '\r' in 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
+        if self.ui.body == entry.body and self.ui.title == entry.title:
+            self.error("You didn't make any changes!")
+            return
+        # XXX Should lock here
+        try:
+            os.unlink(file)
+        except os.error:
+            pass
+        try:
+            f = open(file, 'w')
+        except IOError, why:
+            self.error(CANTWRITE, file=file, why=why)
+            return
+        date = time.ctime(now)
+        emit(FILEHEADER, self.ui, os.environ, date=date, _file=f, _quote=0)
+        f.write('\n')
+        f.write(self.ui.body)
+        f.write('\n')
+        f.close()
+
+        import tempfile
+        tfn = tempfile.mktemp()
+        f = open(tfn, 'w')
+        emit(LOGHEADER, self.ui, os.environ, date=date, _file=f)
+        f.close()
+
+        command = interpolate(
+            SH_LOCK + '\n' + SH_CHECKIN,
+            file=file, tfn=tfn)
+
+        p = os.popen(command)
+        output = p.read()
+        sts = p.close()
+        # XXX Should unlock here
+        if not sts:
+            self.prologue(T_COMMITTED)
+            emit(COMMITTED)
+        else:
+            self.error(T_COMMITFAILED)
+            emit(COMMITFAILED, sts=sts)
+        print '<PRE>%s</PRE>' % escape(output)
+
+        try:
+            os.unlink(tfn)
+        except os.error:
+            pass
+
+        entry = self.dir.open(file)
+        entry.show()
 
 wiz = FaqWizard()
 wiz.go()