- commit
- 746d6a6ef5c61d0ac1672fe724cecdf6ecf27812
- parent
- f4a35784689dd2e81e71773df59e47b7d73fdbb3
- Author
- Tobias Bengfort <tobias.bengfort@posteo.de>
- Date
- 2024-07-05 17:31
use (x, y) instead of A1 internally
Diffstat
| M | sheet/__main__.py | 2 | +- |
| M | sheet/csv.py | 6 | ++---- |
| M | sheet/expression.py | 26 | ++++++++++++++++++++++++-- |
| M | sheet/sheet.py | 46 | ++++++++++------------------------------------ |
| M | sheet/term.py | 8 | +++----- |
5 files changed, 40 insertions, 48 deletions
diff --git a/sheet/__main__.py b/sheet/__main__.py
@@ -7,4 +7,4 @@ from .term import render 7 7 with open(sys.argv[1]) as fh: 8 8 sheet = load_csv(fh) 9 910 -1 print(render(sheet, 80, 40, 'A1', 10))-1 10 print(render(sheet, 80, 40, (0, 0), 10))
diff --git a/sheet/csv.py b/sheet/csv.py
@@ -1,7 +1,6 @@ 1 1 import csv 2 2 3 3 from .sheet import Sheet4 -1 from .sheet import xy2ref5 4 6 5 7 6 def to_display(value: float|int|str|None|Exception) -> str: @@ -21,8 +20,7 @@ def load_csv(fh, **kwargs): 21 20 sheet = Sheet() 22 21 for y, row in enumerate(csv.reader(fh, **kwargs)): 23 22 for x, raw in enumerate(row):24 -1 ref = xy2ref(x, y)25 -1 sheet.set(ref, raw)-1 23 sheet.set((x, y), raw) 26 24 return sheet 27 25 28 26 @@ -35,4 +33,4 @@ def dump_csv(sheet, fh, *, display=False, **kwargs): 35 33 36 34 w = csv.writer(fh, **kwargs) 37 35 for y in range(sheet.height):38 -1 w.writerow([get(xy2ref(x, y)) for x in range(sheet.width)])-1 36 w.writerow([get((x, y)) for x in range(sheet.width)])
diff --git a/sheet/expression.py b/sheet/expression.py
@@ -1,4 +1,5 @@ 1 1 import re -1 2 import string 2 3 3 4 4 5 class ParseError(ValueError): @@ -36,9 +37,30 @@ def parse_int(text): 36 37 return ('int', int(m[0], 10)), tail 37 38 38 39 -1 40 def col2x(col): -1 41 alph = string.ascii_uppercase -1 42 x = -1 -1 43 for c in col: -1 44 x = (x + 1) * len(alph) + alph.index(c) -1 45 return x -1 46 -1 47 -1 48 def x2col(x): -1 49 a, b = divmod(x, len(string.ascii_uppercase)) -1 50 s = string.ascii_uppercase[b] -1 51 while a: -1 52 a, b = divmod(a - 1, len(string.ascii_uppercase)) -1 53 s = string.ascii_uppercase[b] + s -1 54 return s -1 55 -1 56 39 57 def parse_ref(text):40 -1 m, tail = parse_re(text, r'\$?([A-Z]+)\$?([1-9][0-9]*)')41 -1 return ('ref', m[1] + m[2], m[0]), tail-1 58 m, tail = parse_re(text, r'(\$)?([A-Z]+)(\$)?([1-9][0-9]*)') -1 59 x_fixed = bool(m[1]) -1 60 x = col2x(m[2]) -1 61 y_fixed = bool(m[3]) -1 62 y = int(m[4], 10) - 1 -1 63 return ('ref', (x, y), (x_fixed, y_fixed)), tail 42 64 43 65 44 66 def parse_range(text):
diff --git a/sheet/sheet.py b/sheet/sheet.py
@@ -5,42 +5,16 @@ from .expression import ParseError 5 5 from .expression import parse 6 6 7 78 -1 def x2col(x):9 -1 a, b = divmod(x, len(string.ascii_uppercase))10 -1 s = string.ascii_uppercase[b]11 -1 while a:12 -1 a, b = divmod(a - 1, len(string.ascii_uppercase))13 -1 s = string.ascii_uppercase[b] + s14 -1 return s15 -116 -117 -1 def xy2ref(x, y):18 -1 return x2col(x) + str(y + 1)19 -120 -121 -1 def col2x(col):22 -1 alph = string.ascii_uppercase23 -1 x = -124 -1 for c in col:25 -1 x = (x + 1) * len(alph) + alph.index(c)26 -1 return x27 -128 -129 -1 def ref2xy(ref):30 -1 m = re.match('([A-Z]*)([0-9]*)', ref)31 -1 return col2x(m[1]), int(m[2], 10) - 132 -133 -134 8 def iter_range(cell1, cell2):35 -1 x1, y1 = ref2xy(cell1)36 -1 x2, y2 = ref2xy(cell2)-1 9 x1, y1 = cell1 -1 10 x2, y2 = cell2 37 11 if x1 > x2: 38 12 x1, x2 = x2, x1 39 13 if y1 > y2: 40 14 y1, y2 = y2, y1 41 15 for y in range(y1, y2 + 1): 42 16 for x in range(x1, x2 + 1):43 -1 yield xy2ref(x, y)-1 17 yield x, y 44 18 45 19 46 20 def to_number(value: float|int|str|None|Exception) -> float|int: @@ -116,27 +90,27 @@ class Sheet: 116 90 else: 117 91 return self.call_function(*expr) 118 92119 -1 def set(self, cell: str, raw: str):-1 93 def set(self, cell, raw: str): 120 94 if raw: 121 95 self.raw[cell] = raw 122 96 self.parsed[cell] = self.parse(raw)123 -1 x, y = ref2xy(cell)-1 97 x, y = cell 124 98 self.width = max(self.width, x + 1) 125 99 self.height = max(self.height, y + 1) 126 100 elif cell in self.raw: 127 101 del self.raw[cell] 128 102 del self.parsed[cell]129 -1 self.width = max(ref2xy(cell)[0] for cell in self.raw) + 1130 -1 self.height = max(ref2xy(cell)[1] for cell in self.raw) + 1-1 103 self.width = max(cell[0] for cell in self.raw) + 1 -1 104 self.height = max(cell[1] for cell in self.raw) + 1 131 105 self.cache = {} 132 106133 -1 def get_raw(self, cell: str) -> str:-1 107 def get_raw(self, cell) -> str: 134 108 return self.raw.get(cell, '') 135 109136 -1 def get_parsed(self, cell: str) -> tuple|float|int|str|None:-1 110 def get_parsed(self, cell) -> tuple|float|int|str|None: 137 111 return self.parsed.get(cell) 138 112139 -1 def get_value(self, cell: str) -> float|int|str|None|Exception:-1 113 def get_value(self, cell) -> float|int|str|None|Exception: 140 114 parsed = self.get_parsed(cell) 141 115 if isinstance(parsed, tuple): 142 116 if cell not in self.cache:
diff --git a/sheet/term.py b/sheet/term.py
@@ -1,6 +1,4 @@1 -1 from .sheet import ref2xy2 -1 from .sheet import x2col3 -1 from .sheet import xy2ref-1 1 from .expression import x2col 4 2 5 3 6 4 def align_right(s, width): @@ -44,7 +42,7 @@ def to_cell(value: float|int|str|None|Exception, width: int) -> str: 44 42 45 43 46 44 def render(sheet, width, height, cell_offset, cell_width):47 -1 x0, y0 = ref2xy(cell_offset)-1 45 x0, y0 = cell_offset 48 46 rows = [] 49 47 w = width // cell_width 50 48 rows.append([ @@ -57,7 +55,7 @@ def render(sheet, width, height, cell_offset, cell_width): 57 55 rows.append([ 58 56 align_right(str(y0 + dy + 1), cell_width), 59 57 ] + [60 -1 to_cell(sheet.get_value(xy2ref(x0 + dx, y0 + dy)), cell_width)-1 58 to_cell(sheet.get_value((x0 + dx, y0 + dy)), cell_width) 61 59 for dx in range(w - 1) 62 60 ]) 63 61 return '\n'.join([''.join(row) for row in rows])