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

一个文本折行的模块

阅读更多

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

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

    1350多个精品易语言模块

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

    790个易模块打包

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

    自己做的as3折叠文本

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

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

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

    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