`
dqifa
  • 浏览: 112084 次
社区版块
存档分类
最新评论

一个文本折行的模块

阅读更多

今天开发了一个wraptext模块,它可以对文本进行折行处理。详情:

 说明
    本程序用来进行文本的折行处理,支持中文和英文,可以处理Unicode和普通字符串

 参数说明
    text       待处理的文本,可以是unicode或str
    width      处理宽度
    encoding   字符串编码,只当text不是unicode时有效
    cr         换行符,如果为None则自动从文本中判断,自动设定为找到的第一个换
               行符,如果找不到缺省为’\n’,如果不为None,则使用设定的换行符
    indent     非首行缩近量
    firstindent首行缩近量
    skipchar   行首忽略字符,如果存在则在处理前会清除每前开始前有skipchar的文本

 功能描述
  1.支持unicode和非unicode文本,如果为非unicode文本,则会使用encoding指定的编
    码对文本转换为unicode,在返回时,会根据原文本是unicode还是非unicode进行转
    换并输出。
  2.支持段落概念。两个以上连续的回车为段落分隔,其中如果一行只包括空白(空格或
    制表符的行)将视为空行。最终的结果段落间只保存一个空行。如果只存在单个换行
    则相邻的行视为同一段落。支持’\n’, ‘\r\n’, ‘\r’三种形式的换行符。可以自动
    使用文本中的回车符或指定转换后的回车符。
  3.自动处理亚洲文字和半角字符,自动处理空白,多个空白(包括制表符)将自动合并
    成一个。亚洲文字和英文之间以空格分隔。对于亚洲文字中间的空白自动删除。
  4.支持缩近设置,首行缩近和非首行缩近。缩近量可以是数值,则为空格*数值,可以
    是字符串。如果firstindent没有设置将缺省为indent的值。
  5.可以设置每行行首要忽略的字符,如注释行的’#',在处理时将先删除匹配的行首字
    符。

 示例
  msg = ”’中文 中文hello, world”’
  wraptext(msg, 10)

现在代码放在 http://code.google.com/p/pyzh 中。原来它已经有一个模块,不过不满足我的要求,于是自已重新写了一个。

 

 

wraptext.py代码如下:

#!/usr/bin/env python
#coding=utf-8
#
# Copyleft 2008 limodou@gmail.com
# License BSD
# Version 0.1
#
# 说明
#    本程序用来进行文本的折行处理,支持中文和英文,可以处理Unicode和普通字符串
#
# 参数说明
#    text       待处理的文本,可以是unicode或str
#    width      处理宽度
#    encoding   字符串编码,只当text不是unicode时有效
#    cr         换行符,如果为None则自动从文本中判断,自动设定为找到的第一个换
#               行符,如果找不到缺省为'\n',如果不为None,则使用设定的换行符
#    indent     非首行缩近量
#    firstindent首行缩近量
#    skipchar   行首忽略字符,如果存在则在处理前会清除每前开始前有skipchar的文本
#    remove_tailingchar   行尾忽略字符,如果存在则在处理前会清除每行行尾匹配的文本
#    add_tailingchar   添加行尾字符,如果存在则在处理后每行最后添加此文本
#
# 功能描述
#  1.支持unicode和非unicode文本,如果为非unicode文本,则会使用encoding指定的编
#    码对文本转换为unicode,在返回时,会根据原文本是unicode还是非unicode进行转
#    换并输出。
#  2.支持段落概念。两个以上连续的回车为段落分隔,其中如果一行只包括空白(空格或
#    制表符的行)将视为空行。最终的结果段落间只保存一个空行。如果只存在单个换行
#    则相邻的行视为同一段落。支持'\n', '\r\n', '\r'三种形式的换行符。可以自动
#    使用文本中的回车符或指定转换后的回车符。
#  3.自动处理亚洲文字和半角字符,自动处理空白,多个空白(包括制表符)将自动合并
#    成一个。亚洲文字和英文之间以空格分隔。对于亚洲文字中间的空白自动删除。
#  4.支持缩近设置,首行缩近和非首行缩近。缩近量可以是数值,则为空格*数值,可以
#    是字符串。如果firstindent没有设置将缺省为indent的值。
#  5.可以设置每行行首要忽略的字符,如注释行的'#',在处理时将先删除匹配的行首字
#    符。
#
# 示例
#  msg = '''中文 中文hello, world'''
#  wraptext(msg, 10)

def wraptext(text, width=75, encoding='utf-8', cr=None, indent='',
    firstindent=None, skipchar=None, remove_tailingchar='', add_tailingchar=''):
    import unicodedata
    import re
    if isinstance(text, unicode):
        unicode_flag = True
    else:
        unicode_flag = False
        text = unicode(text, encoding)

    if text[-1] in ('\r', '\n'):
        enter_flag = True
    else:
        enter_flag = False

    if not cr:
        if text.find('\r\n') > -1:
            cr = '\r\n'
        elif text.find('\r') > -1:
            cr = '\r'
        else:
            cr = '\n'

    text = text.replace('\r\n', '\n')
    text = re.sub(r'\s+$', '\n', text)
    if skipchar:
        text = re.sub(r'(?m)^%s' % skipchar, '', text)
    if remove_tailingchar:
        _r = re.compile('%s\n' % re.escape(remove_tailingchar), re.MULTILINE)
        text = _r.sub('\n', text)

    lines = re.split(r'(\n\s*\n+|\r\r+)', text)
    rx = re.compile(u"[\u2e80-\uffff]+", re.UNICODE)

    if isinstance(indent, int):
        indent = ' ' * indent
    if firstindent is None:
        firstindent = indent
    if isinstance(firstindent, int):
        firstindent = ' ' * firstindent

    def _add_line(line, buf, tailing=add_tailingchar):
        line.append(buf + tailing)

    def _wrap(text, width, indent, firstindent):
        if not text:
            return ''
        text = text.strip()
        s = []
        pos = 0
        for i in rx.finditer(text):
            if i.start() > pos:
                s.extend(text[pos:i.start()].split())
            s.append(i.group())
            pos = i.end()
        if pos < len(text):
            s.extend(text[pos:].split())

        ss = [s[0]]
        #get first element character is asian char flag
        flag = unicodedata.east_asian_width(s[0][0]) != 'Na'
        for i in range(1, len(s)):
            f = unicodedata.east_asian_width(s[i][0]) != 'Na'
            if f and f == flag:
                ss[-1] = ss[-1] + s[i]
            else:
                ss.append(s[i])
            flag = f

        s = ss

        t = []
        y = 0
        buf = []
        x = 0
        while s:
            i = s.pop(0)
            if unicodedata.east_asian_width(i[0]) != 'Na':
                factor = 2
            else:
                factor = 1

            if x == 0:
                w = width - len(firstindent)
                step = firstindent
            else:
                w = width - len(indent)
                step = indent
            length = y + len(i)*factor + len(buf)
#            print 'length', length, s[0].encode('gbk')
            if length == w:
                buf.append(i)
                _add_line(t, step + ' '.join(buf))
#                t.append(step + ' '.join(buf))
                x = 1
                buf = []
                y = 0
            elif length > w:
                if factor == 2 or (factor==1 and len(i) * factor >= w):
                    buf_len = len(buf)
                    rest = w-y-buf_len
                    buf.append(i[:rest/factor])
#                    print '----', w, y, buf_len, (w-y-buf_len-1), buf
                    _add_line(t, step + ' '.join(buf))
#                    t.append(step + ' '.join(buf))
                    x = 1
                    s.insert(0, i[rest/factor:])
                    buf = []
                    y = 0
                    continue
                else:
                    _add_line(t, step + ' '.join(buf))
#                    t.append(step + ' '.join(buf))
                    x = 1
                    s.insert(0, i)
                    buf = []
                    y = 0
                    continue

            else:
                buf.append(i)
                y += factor * len(i)

        if buf:
            _add_line(t, step + ' '.join(buf), '')
#            t.append(step + ' '.join(buf))
        return cr.join(t)

    s = []
    for line in lines:
        if not line.strip():
            s.append(indent)
        else:
            s.append(_wrap(line, width, indent, firstindent))

    if enter_flag:
        s.append('')
    text = cr.join(s)
    if not unicode_flag:
        text = text.encode(encoding)
    return text

def test():
    msg =u"""首先这个框架是一个试验品,或者说是主要是个人使用,因此我将有完全的控制权,这一点很重要。我可以用它学到许多框架的知识。以前只是使用,学习,象学过:cherrypy, Karrigell, snakelets等,不过没有做过什么开发;zope则是我学得最早了,不过也早就放弃了;django投入的精力最多,也开发了不少东西;再后来就是 web2py了,不过重用搞得我很不爽,而且有些想法不被认同。但这些更多的还是集中在开发方面,对于框架本身了解有限,这次造轮是一个好机会。"""
    print wraptext(msg, 75, indent='', skipchar='#', remove_tailingchar='',add_tailingchar='').encode('gbk')

if __name__ == '__main__':
#    from timeit import Timer
#    t = Timer("test()", "from __main__ import test")
#    print t.timeit(1000)
    test()

 

from:http://blog.donews.com/limodou/archive/2008/04/18/1279041.aspx

分享到:
评论

相关推荐

    完整版模块_文本折行.rar

    完整版模块_文本折行.rar

    易语言源码模块_文本折行.7z

    易语言源码模块_文本折行.7z

    模块_文本折行.zip易语言程序源码资源下载

    模块_文本折行.zip易语言程序源码资源下载模块_文本折行.zip易语言程序源码资源下载 1.适合学生做毕业设计用 2.适合程序员学习研究用 3.适合新手自学研究使用

    易语言模块文本分行1.0.rar

    易语言模块文本分行1.0.rar

    搜集和整理的1300多个易语言模块,易语言模块大集合.zip

    文本折行.ec 文本操作.EC 文本操作1.0.EC 文本操作模块.ec 文本数字统计.ec 文本替换模块.ec 文本查找.ec 文本统计模块 1.0.ec 文本计算.ec 文本语音朗读.ec 文本语音朗读1.1.ec 文本语音转换模块.EC 斑马模块.ec ...

    易语言模块大全(共775个模块)

    易语言模块大全,里面包含775个模块!!! 易语言模块大全,里面包含775个模块!!! 易语言模块大全,里面包含775个模块!!! ACCESS到高级表格1.1(1.1).zip Access操作(1.0).zip ACCESS到超级列表框(1.0).zip ...

    2020易语言模块大全持续更新3.zip

    文本折行.ec 文本操作1.0.EC 文本操作模块.ec 文本数字统计.ec 文本替换模块.ec 文本统计模块 1.0.ec 文本计算.ec 文本语音朗读.ec 文本语音转换模块.EC 斩月内测版.ec 新创建查询快捷方式.ec 新查询快捷方式.ec 新...

    790个易模块-3

    模块_文本折行.ec 模块_无边框窗口设置.ec 模块_系统功能.ec 模块_修改菜单.ec 模块_与黄金加密建立关联.ec 模块_与狡兔三窟建立关联.ec 模块_与应用程序建立关联.ec 模块_在线更新.ec 模块集.ec 模拟XP.ec...

    790个易模块打包

    模块_文本折行.ec 模块_无边框窗口设置.ec 模块_系统功能.ec 模块_修改菜单.ec 模块_与黄金加密建立关联.ec 模块_与狡兔三窟建立关联.ec 模块_与应用程序建立关联.ec 模块_在线更新.ec 模块集.ec 模拟XP.ec...

    1345个易语言模块

    1345个易语言模块,易语言模块大集合,够你用的啦 1亦思验证码识别1.5免费版.ec 24位转单色位图模块.ec 32张发牌.ec 3D引擎支持库-eOgre.ec 69msn.ec ACCESS 到高级表格.ec Access操作.ec Access数据库压缩修复新建....

    790个易模块打包下载-2

    模块_文本折行.ec 模块_无边框窗口设置.ec 模块_系统功能.ec 模块_修改菜单.ec 模块_与黄金加密建立关联.ec 模块_与狡兔三窟建立关联.ec 模块_与应用程序建立关联.ec 模块_在线更新.ec 模块集.ec 模拟XP.ec...

    易语言模块914个

    删除文本所在行.ec 判断ASCII编码.ec 判断XP外观支持文件是否存在.ec 判断字符模块.ec 判断数据库.ec 判断进程是否存在的模块.ec 到文本.ec 办公组件密码管理模块.ec 功能集一模块 1.0.ec 功能集一模块.ec...

    易语言模块大全(401个)

    模块_文本折行.ec 模块_磁盘操作.ec 外挂作坊1.40909.ec 屏蔽超文本浏览框右键菜单2.2.ec 伟业高级表格列宽尺寸自动调整.ec eOgre.ec 模块_数制转换.ec 多表格载入ADO数据.ec 控件自动缩放.ec 多种对话框模块.ec 仿...

    E语言1000模块

    2004-12-01 08:13 6412 2158 易语言模块大全\SQL到文本.ec 2006-03-29 04:40 4961 1740 易语言模块大全\SQL基本语句.ec 2006-01-04 14:21 77791 19069 易语言模块大全\sql操作模块.ec 2005-10-21 15:30 8193 2748...

    易语言540个易模块

    模块_图片按钮v2.0 模块_文本折行 模块_无边框窗口设置 模块_系统功能 模块_修改菜单 模块_与黄金加密建立关联 模块_与狡兔三窟建立关联 模块_与应用程序建立关联 模块_在线更新 模块集 模拟XP 模拟按键 目录...

    易语言模块大全汇总批量下载

    2004-12-01 08:13 6412 2158 易语言模块大全\SQL到文本.ec 2006-03-29 04:40 4961 1740 易语言模块大全\SQL基本语句.ec 2006-01-04 14:21 77791 19069 易语言模块大全\sql操作模块.ec 2005-10-21 15:30 8193 2748 ...

    1350多个精品易语言模块

    1350多个精品易语言模块提供下载介绍 1亦思验证码识别1.5免费版.ec 24位转单色位图模块.ec 32张发牌.ec 3D引擎支持库-eOgre.ec 69msn.ec ACCESS 到高级表格.ec Access操作.ec Access数据库压缩修复新建.ec ACCSEE...

    易语言700模块打包

    取中文文本拼音首个字母(1.0).zip 取拼音首(1.0).zip 取按键名称模块(1.0).zip 取控件或窗口的标题(1.0).zip 取操作系统类别(1.0).zip 取文件对应图标(1.0).zip 取文本文件行数(1.0).zip 取易模块信息(1.0)....

Global site tag (gtag.js) - Google Analytics