class FluidString(object): def __init__(self, actual, limit, prefix="", suffix=""): self.actual = actual self.limit = limit self.prefix = prefix self.suffix = suffix def increase_limit_by(self, amt): self.limit += amt def __str__(self): # adding newline is a hack, specific for my app, # where I want each fluid string to be # contained in a seperate line t = len(self.prefix) + len(self.suffix) if self.limit < t: return self.actual[:self.limit] s = self.actual[:self.limit-1-t] return self.prefix + s + self.suffix + "\n" # returns non-negative integer: def chars_left_over(self): return max(self.limit - len(str(self)), 0)
Fluid strings are assembled by containers:
# right now just fits pieces fluidly; # if any piece underflows, other pieces # evenly get what's left over. class Container(object): def __init__(self, *items): self.strings = list(items) def add(self, fs): self.strings.append(fs) # unused: def on_underflow_of(self, target, *fs_pairs): pass def render(self): # find fluid strings that are underflowing. # split all those free spaces among strings that # are likely to overflow. anyleft = [x.chars_left_over() for x in self.strings] freespace = sum(anyleft) # how many to split freespace with: # `if not x': it means that the fluid string # will likely overflow. so split space among # those likely to overflow count = anyleft.count(0) #sum(1 for i in anyleft if i==0) if freespace and count: amount = freespace / count for i, x in enumerate(self.strings): if not anyleft[i]: x.increase_limit_by(amount) final = "".join(str(x) for x in self.strings) #assert len(final) == sum(x.limit for x in self.strings) return final @staticmethod def test(): c = Container() c.add(FluidString("01234567890123456789", 10)) c.add(FluidString("asdf", 20)) c.add(FluidString("hello world how are you", 10)) return c.render()
Here is an usage sample (it is also above):
def test(): c = Container() c.add(FluidString("01234567890123456789", 10)) c.add(FluidString("asdf", 20)) c.add(FluidString("hello world how are you", 10)) return c.render()The output is:
01234567890123456 asdf hello world how a [newline](Note how the first & third FluidString added, shows more than its limit allows it — extra 7 characters each + 2 newlines.)