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

一个文本折行的模块

阅读更多

今天开发了一个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

    "模块_文本折行"可能是一个专门处理这些情况的代码模块,包括解析、转换、格式化等功能,方便开发者在项目中集成和使用。如果这个压缩包包含源码,我们可以学习其内部实现,提升自己在文本处理方面的能力。同时,...

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

    模块_文本折行可能是易语言中实现这些功能的一个自定义模块,可能包含了一些预定义的函数或者过程,如`TextWrap()`或`WordWrap()`,用于处理文本的自动折行。使用这样的模块,开发者可以方便地在程序中集成文本折行...

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

    本资源包“模块_文本折行.zip”是针对易语言用户的一个程序源码资源,特别适用于学生进行毕业设计、程序员学习研究以及初学者自我提升。 一、易语言基础 易语言的核心理念是“易”,其语法简洁明了,采用汉字编程...

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

    模块的主体部分,"模块文本分行1.0",是易语言程序设计中的一个重要组成部分。在易语言中,模块是一种可以复用的代码单元,包含了特定功能的系列命令和过程。开发者可以将常用的功能封装成模块,以便在多个项目中...

    搜集和整理的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 ...

    易语言模块914个

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

    1345个易语言模块

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

    计算机软件-编程源码-DW中文本折行.zip

    标题中的“计算机软件-编程源码-DW中文本折行.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...

    自己做的as3折叠文本

    "自己做的AS3折叠文本"这个项目可能是指开发者自制的一个功能,允许用户在界面中显示可展开和收起的文本块,以提高用户体验和页面的整洁度。 折叠文本通常涉及到以下几个关键技术点: 1. **事件监听**:AS3中,...

    1350多个精品易语言模块

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

    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...

    易语言模块大全(401个)

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

    790个易模块打包下载-2

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

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

    模块_文本折行.ec 模块_无边框窗口设置.ec 模块_树型框.ec 模块_汉字查询.ec 模块_磁盘操作.ec 模块_禁止多次运行.ec 模块_系统功能.ec 模块_菜单项加图片.ec 模块_超级列表框.ec 模块_超级列表框快速排序2.0.ec ...

    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 ...

Global site tag (gtag.js) - Google Analytics