Python食谱-1.25.在Unix终端上格式化显示HTML文本

原文作者:Brent Burley, Mark Moraes
中文翻译:Tony (digitalsatori)

问题

如何才能在Unix终端上显示HTML文本,使其可以表现粗体和下划线。

解决方案

最简单的方法是编制一个过滤脚本,从标准输入获取HTML然后在标准输出文本和终端控制符。因为本配方针对得唯一对象是Unix, 我们可以通过Unix命令 tput 来获取需要的终端控制符。具体方法是使用Python标准库中os模块中得popen函数来启动tput。

#!/usr/bin/env python
import sys, os, htmllib, formatter
# use Unix tput to get the escape sequences for bold, underline, reset
set_bold = os.popen('tput bold').read( )
set_underline = os.popen('tput smul').read( )
perform_reset = os.popen('tput sgr0').read( )
class TtyFormatter(formatter.AbstractFormatter):
    ''' a formatter that keeps track of bold and italic font states, and
        emits terminal control sequences accordingly.
    '''
    def _ _init_ _(self, writer):
        # first, as usual, initialize the superclass
        formatter.AbstractFormatter._ _init_ _(self, writer)
        # start with neither bold nor italic, and no saved font state
        self.fontState = False, False
        self.fontStack = [  ]
    def push_font(self, font):
        # the `font' tuple has four items, we only track the two flags
        # about whether italic and bold are active or not
        size, is_italic, is_bold, is_tt = font
        self.fontStack.append((is_italic, is_bold))
        self._updateFontState( )
    def pop_font(self, *args):
        # go back to previous font state
        try:
            self.fontStack.pop( )
        except IndexError:
            pass
        self._updateFontState( )
    def updateFontState(self):
        # emit appropriate terminal control sequences if the state of
        # bold and/or italic(==underline) has just changed
        try:
            newState = self.fontStack[-1]
        except IndexError:
            newState = False, False
        if self.fontState != newState:
            # relevant state change: reset terminal
            print perform_reset,
            # set underine and/or bold if needed
            if newState[0]:
                print set_underline,
            if newState[1]:
                print set_bold,
            # remember the two flags as our current font-state
            self.fontState = newState
# make writer, formatter and parser objects, connecting them as needed
myWriter = formatter.DumbWriter( )
if sys.stdout.isatty( ):
    myFormatter = TtyFormatter(myWriter)
else:
    myFormatter = formatter.AbstractFormatter(myWriter)
myParser = htmllib.HTMLParser(myFormatter)
# feed all of standard input to the parser, then terminate operations
myParser.feed(sys.stdin.read( ))
myParser.close( )

讨论

Python标准库中的 formatter.AbstractFormatter 基本类可以工作在任何地方。而本配方中的 TtyFormatter 子类則依赖于类Unix的终端。确切的说是依赖于Unix命令 tput , 利用其获取控制符以输出粗体或下划线,并可以重置终端状态。

本配方中的方法要求只要系统中有 tput 命令即可工作,所以本配方可以工作于包括Linux,Mac OS X 在内的大多数类Unix系统。

如果你的终端模拟器支持其他控制输出样式的控制符,你可以对 TtyFormatter 做响应的调整。比如,在Windows系统上,cmd.exe 命令窗口支持标准ANSI控制符。你可以将这些控制符编入要运行的脚本中。

多数情况下,你可能倾向于使用诸如 lynx -dump - 这样的Unix命令,以获得比本配方更加丰富的输出格式。但是如果你正好面对一个没有 lynx 命令的系统,而该系统又恰好安装有Python,那么本配方的方法就很有用了。

参见

Python标准库参考手册和Python in a Nutshell 中关于 formatterhtmllib 模块的介绍;使用 man tput 来了解更多关于 tput 的信息。

Leave a Response