# HG changeset patch # User David Barts # Date 1577419444 28800 # Node ID 7a83e82e65a6062edd68bdf2971a68778e3f8ccb # Parent 091c03f1b2e865fe1c022ac0e314815f5fe7b478 Remove some deadwood. diff -r 091c03f1b2e8 -r 7a83e82e65a6 curlers.py --- a/curlers.py Thu Dec 26 19:54:45 2019 -0800 +++ b/curlers.py Thu Dec 26 20:04:04 2019 -0800 @@ -32,6 +32,17 @@ # F u n c t i o n s +def uncurl(ws): + """ + Makes all quotes in the workspace non-curly. + """ + for i in range(len(ws)): + ch = ws[i] + if ch in set([LDQUO, RDQUO]): + ws[i] = '"' + elif ch in set([LSQUO, RSQUO]): + ws[i] = "'" + def _is_cockney(pos, ws): pos = self._pos ws = self.workspace diff -r 091c03f1b2e8 -r 7a83e82e65a6 curlyq --- a/curlyq Thu Dec 26 19:54:45 2019 -0800 +++ b/curlyq Thu Dec 26 20:04:04 2019 -0800 @@ -5,8 +5,8 @@ import argparse import codecs -from curlers import TextCurler, HtmlCurler -from workspace import Workspace, Bounds, Mapping, SegmentedView +from curlers import TextCurler, HtmlCurler, uncurl +from workspace import Workspace from writer import CODECS_TO_NAME # V a r i a b l e s @@ -21,13 +21,14 @@ # F u n c t i o n s def normal(): - global input_fp, output_fp + global input_fp, output_fp, args with Workspace() as ws: curler = TextCurler(ws) while True: line = input_fp.readline() ws.write(line) if line == "" or line == "\n": + if args.force: uncurl(ws) curler.feed() output_fp.write(ws.getvalue()) ws.clear() @@ -43,6 +44,7 @@ if line == "": break ws.write(line) + if args.force: uncurl(ws) curler.feed() output_fp.write(ws.getvalue()) ws.clear() @@ -51,6 +53,7 @@ global input_fp, output_fp with Workspace(input_fp.read()) as ws: curler = HtmlCurler(ws) + if args.force: uncurl(ws) curler.feed() output_fp.write(ws.getvalue()) diff -r 091c03f1b2e8 -r 7a83e82e65a6 workspace.py --- a/workspace.py Thu Dec 26 19:54:45 2019 -0800 +++ b/workspace.py Thu Dec 26 20:04:04 2019 -0800 @@ -1,9 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -# Classes that implement a workspace for curly-quoting a text, and views -# into the same. - # I m p o r t s import os, sys @@ -182,157 +179,3 @@ """ self.close() return False - -class Bounds(object): - """ - A set of index bounds. - """ - def __init__(self, start, stop): - if start > stop or start < 0 or stop < 0: - raise ValueError("invalid bounds") - self.start = int(start) - self.stop = int(stop) - - @classmethod - def from_object(cls, obj): - if isinstance(obj, slice): - return self(slice.start, slice.stop) - return self(obj[0], obj[1]) - - def __lt__(self, other): - return self.start < other.start - - def __le__(self, other): - return self.start <= other.start - - def __eq__(self, other): - return self.start == other.start - - def __ne__(self, other): - return self.start != other.start - - def __gt__(self, other): - return self.start > other.start - - def __ge__(self, other): - return self.start >= other.start - - def __contains__(self, scalar): - return self.start <= scalar < self.stop - - def __repr__(self): - return "{0}({1!r}, {2!r})".format(self.__class__.__name__, self.start, self.stop) - -class Mapping(object): - """ - Represents a mapping of a single view segment into an indexable - object. - """ - def __init__(self, bounds, offset): - if not isinstance(bounds, Bounds): - raise TypeError("bounds must be a Bounds object") - if not isinstance(offset, int): - raise TypeError("offset must be an int") - self.bounds = bounds - self.offset = offset - self.delta = self.offset - self.bounds.start - - def __repr__(self): - return "{0}({1!r}, {2!r})".format(self.__class__.__name__, self.bounds, self.offset) - -class SegmentedView(object): - """ - Implements a view on a subscriptable object. The view is composed of - zero or more segments of the source object. Has the same idiosyncratic - behavior for out-of-bounds indices that Workspace has (and for the - same reason). Mutating this object causes the parent object to also - be mutated. - """ - def __init__(self, indexable, bounds): - self.indexable = indexable - self._mmap = [ Mapping(Bounds(0, 0), 0) ] - pos = 0 - for r in sorted(bounds): - if pos is not None and r.start <= pos and r.stop > pos: - # merge ranges - self._mmap[-1].bounds.stop = r.stop - pos = r.stop - continue - opos = pos - pos += r.stop - r.start - self._mmap.append(Mapping(Bounds(opos, pos), r.start)) - self._length = pos - - def _mapped(self, index): - mmap_index = self._binsch(index) - if mmap_index is None: - raise IndexError("index {0} out of range".format(index)) - return index + self._mmap[mmap_index].delta - - def _binsch(self, index): - a = 0 - z = len(self._mmap) - 1 - while a <= z: - m = (a + z) // 2 - if index in self._mmap[m].bounds: - return m - if index < self._mmap[m].bounds.start: - z = m - 1 - else: - assert index >= self._mmap[m].bounds.stop - a = m + 1 - return None - - def __setitem__(self, key, value): - """ - Direct access to replace a single character. - """ - if not isinstance(key, int): - raise TypeError("__setitem__ only supports integers") - self.indexable[self._mapped(key)] = value - - def __getitem__(self, key): - """ - Direct access to a single character or range of characters. - """ - # Trivial cases - if isinstance(key, int): - return self._get1(key) - if not isinstance(key, slice): - raise TypeError("expecting int or slice") - if key.step is not None: - raise ValueError("__getitem__ does not support steps in slices") - - # Loop up the starting segment. - mi = self._binsch(key.start) - if mi is None: - return "" - m = self._mmap[mi] - - # Horray! There's only one segment, so we can optimize. - if key.stop <= m.bounds.stop: - start = key.start + m.delta - stop = key.stop + m.delta - return self.indexable[start:stop] - - # The most involved (multi-segment) case. - with io.StringIO() as buf: - for m in self._mmap[mi:]: - if m.bounds.start >= key.stop: - break - start = max(key.start, m.bounds.start) + m.delta - stop = min(key.stop, m.bounds.stop) + m.delta - buf.write(self.indexable[start:stop]) - return buf.getvalue() - - def __len__(self): - return self._length - - def _get1(self, index): - try: - return self.indexable[self._mapped(index)] - except IndexError: - return "" - - def getvalue(self): - return self[0:len(self)]