~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/rio.py

  • Committer: Robert Collins
  • Date: 2007-07-04 08:08:13 UTC
  • mfrom: (2572 +trunk)
  • mto: This revision was merged to the branch mainline in revision 2587.
  • Revision ID: robertc@robertcollins.net-20070704080813-wzebx0r88fvwj5rq
Merge bzr.dev.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# Copyright (C) 2005 by Canonical Ltd
2
 
#
3
 
# Distributed under the GNU General Public Licence v2
 
1
# Copyright (C) 2005 Canonical Ltd
 
2
#
 
3
# This program is free software; you can redistribute it and/or modify
 
4
# it under the terms of the GNU General Public License as published by
 
5
# the Free Software Foundation; either version 2 of the License, or
 
6
# (at your option) any later version.
 
7
#
 
8
# This program is distributed in the hope that it will be useful,
 
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
# GNU General Public License for more details.
 
12
#
 
13
# You should have received a copy of the GNU General Public License
 
14
# along with this program; if not, write to the Free Software
 
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
4
16
 
5
17
# \subsection{\emph{rio} - simple text metaformat}
6
18
303
315
        return stanza
304
316
    else:     # didn't see any content
305
317
        return None    
 
318
 
 
319
 
 
320
def to_patch_lines(stanza, max_width=72):
 
321
    """Convert a stanza into RIO-Patch format lines.
 
322
 
 
323
    RIO-Patch is a RIO variant designed to be e-mailed as part of a patch.
 
324
    It resists common forms of damage such as newline conversion or the removal
 
325
    of trailing whitespace, yet is also reasonably easy to read.
 
326
 
 
327
    :param max_width: The maximum number of characters per physical line.
 
328
    :return: a list of lines
 
329
    """
 
330
    assert max_width > 6
 
331
    max_rio_width = max_width - 4
 
332
    lines = []
 
333
    for pline in stanza.to_lines():
 
334
        for line in pline.split('\n')[:-1]:
 
335
            line = re.sub('\\\\', '\\\\\\\\', line)
 
336
            while len(line) > 0:
 
337
                partline = line[:max_rio_width]
 
338
                line = line[max_rio_width:]
 
339
                if len(line) > 0 and line[0] != [' ']:
 
340
                    break_index = -1
 
341
                    break_index = partline.rfind(' ', -20)
 
342
                    if break_index < 3:
 
343
                        break_index = partline.rfind('-', -20)
 
344
                        break_index += 1
 
345
                    if break_index < 3:
 
346
                        break_index = partline.rfind('/', -20)
 
347
                    if break_index >= 3:
 
348
                        line = partline[break_index:] + line
 
349
                        partline = partline[:break_index]
 
350
                if len(line) > 0:
 
351
                    line = '  ' + line
 
352
                partline = re.sub('\r', '\\\\r', partline)
 
353
                blank_line = False
 
354
                if len(line) > 0:
 
355
                    partline += '\\'
 
356
                elif re.search(' $', partline):
 
357
                    partline += '\\'
 
358
                    blank_line = True
 
359
                lines.append('# ' + partline + '\n')
 
360
                if blank_line:
 
361
                    lines.append('#   \n')
 
362
    return lines
 
363
 
 
364
 
 
365
def _patch_stanza_iter(line_iter):
 
366
    map = {'\\\\': '\\',
 
367
           '\\r' : '\r',
 
368
           '\\\n': ''}
 
369
    def mapget(match):
 
370
        return map[match.group(0)]
 
371
 
 
372
    last_line = None
 
373
    for line in line_iter:
 
374
        if line.startswith('# '):
 
375
            line = line[2:]
 
376
        else:
 
377
            assert line.startswith('#')
 
378
            line = line[1:]
 
379
        if last_line is not None and len(line) > 2:
 
380
            line = line[2:]
 
381
        line = re.sub('\r', '', line)
 
382
        line = re.sub('\\\\(.|\n)', mapget, line)
 
383
        if last_line is None:
 
384
            last_line = line
 
385
        else:
 
386
            last_line += line
 
387
        if last_line[-1] == '\n':
 
388
            yield last_line
 
389
            last_line = None
 
390
    if last_line is not None:
 
391
        yield last_line
 
392
 
 
393
 
 
394
def read_patch_stanza(line_iter):
 
395
    """Convert an iterable of RIO-Patch format lines into a Stanza.
 
396
 
 
397
    RIO-Patch is a RIO variant designed to be e-mailed as part of a patch.
 
398
    It resists common forms of damage such as newline conversion or the removal
 
399
    of trailing whitespace, yet is also reasonably easy to read.
 
400
 
 
401
    :return: a Stanza
 
402
    """
 
403
    return read_stanza(_patch_stanza_iter(line_iter))