spreadsheet

terminal spreadsheet application
git clone https://git.ce9e.org/spreadsheet.git

commit
297cf7655232c138c3e2ed0ddf409cbe943fd05d
parent
a9482827297773669100a931f785dbb2f6f2b2c0
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-07-06 06:13
add input

Diffstat

M sheet/__main__.py 24 +++++++++++++++++++++---
A sheet/input.py 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++

2 files changed, 76 insertions, 3 deletions


diff --git a/sheet/__main__.py b/sheet/__main__.py

@@ -4,11 +4,12 @@ import boon
    4     4 
    5     5 from .csv import load_csv
    6     6 from .expression import x2col
   -1     7 from .input import Input
    7     8 from .term import align_center
    8     9 from .term import align_left
    9    10 from .term import align_right
   10    -1 from .term import red
   11    11 from .term import invert
   -1    12 from .term import red
   12    13 
   13    14 
   14    15 def to_cell(value: float|int|str|None|Exception, width: int) -> str:
@@ -34,6 +35,7 @@ class App(boon.App):
   34    35         self.cursor_x = 0
   35    36         self.cursor_y = 0
   36    37         self.widths = {}
   -1    38         self.input = None
   37    39 
   38    40     def scroll_into_view(self, rows, cols):
   39    41         if self.cursor_y < self.y0:
@@ -89,7 +91,10 @@ class App(boon.App):
   89    91                 lines[-1] += cell
   90    92                 x += 1
   91    93 
   92    -1         lines.append(self.sheet.get_raw((self.cursor_x, self.cursor_y)))
   -1    94         if self.input:
   -1    95             lines.append(self.input.render(cols))
   -1    96         else:
   -1    97             lines.append(self.sheet.get_raw((self.cursor_x, self.cursor_y)))
   93    98 
   94    99         return lines
   95   100 
@@ -103,7 +108,17 @@ class App(boon.App):
  103   108         old = self.get_width(x)
  104   109         self.set_width(x, old + d)
  105   110 
   -1   111     def submit_input(self):
   -1   112         self.sheet.set((self.cursor_x, self.cursor_y), self.input.value)
   -1   113         self.input = None
   -1   114 
   -1   115     def cancel_input(self):
   -1   116         self.input = None
   -1   117 
  106   118     def on_key(self, key):
   -1   119         if self.input:
   -1   120             return self.input.on_key(key)
   -1   121 
  107   122         if key == 'q':
  108   123             self.running = False
  109   124         elif key == boon.KEY_DOWN:
@@ -126,7 +141,10 @@ class App(boon.App):
  126   141             pass
  127   142             # self.set_width(self.cursor_x, max()  # TODO auto width
  128   143         elif key == '\n':
  129    -1             pass  # TODO: edit
   -1   144             raw = self.sheet.get_raw((self.cursor_x, self.cursor_y))
   -1   145             self.input = Input(raw, self.submit_input, self.cancel_input)
   -1   146         elif key == boon.KEY_DEL:
   -1   147             self.sheet.set((self.cursor_x, self.cursor_y), '')
  130   148 
  131   149 
  132   150 app = App()

diff --git a/sheet/input.py b/sheet/input.py

@@ -0,0 +1,55 @@
   -1     1 import string
   -1     2 
   -1     3 import boon
   -1     4 
   -1     5 from .term import invert
   -1     6 
   -1     7 
   -1     8 class Input:
   -1     9     def __init__(self, value, submit, cancel):
   -1    10         self.value = value
   -1    11         self.cursor = len(value)
   -1    12         self.offset = 0
   -1    13         self.submit = submit
   -1    14         self.cancel = cancel
   -1    15 
   -1    16     def scroll_into_view(self, cols):
   -1    17         if self.cursor < self.offset:
   -1    18             self.offset = self.cursor
   -1    19         elif self.cursor > self.offset + cols - 1:
   -1    20             self.offset = self.cursor - cols + 1
   -1    21 
   -1    22     def render(self, cols):
   -1    23         self.scroll_into_view(cols)
   -1    24         v = self.value + ' '
   -1    25         return (
   -1    26             v[self.offset:self.cursor]
   -1    27             + invert(v[self.cursor])
   -1    28             + v[self.cursor + 1:self.offset + cols]
   -1    29         )
   -1    30 
   -1    31     def on_key(self, key):
   -1    32         # TODO ctrl-left/right to jump words
   -1    33         # TODO del
   -1    34         if key == boon.KEY_LEFT:
   -1    35             self.cursor = max(self.cursor - 1, 0)
   -1    36         elif key == boon.KEY_RIGHT:
   -1    37             self.cursor = min(self.cursor + 1, len(self.value))
   -1    38         elif key == boon.KEY_HOME:
   -1    39             self.cursor = 0
   -1    40         elif key == boon.KEY_END:
   -1    41             self.cursor = len(self.value)
   -1    42         elif key == boon.KEY_BACKSPACE:
   -1    43             if self.cursor > 0:
   -1    44                 self.value = self.value[:self.cursor - 1] + self.value[self.cursor:]
   -1    45                 self.cursor -= 1
   -1    46         elif key == chr(27):
   -1    47             self.cancel()
   -1    48         elif key == '\n':
   -1    49             self.submit()
   -1    50         elif key.isprintable():
   -1    51             self.value += key
   -1    52             self.cursor += len(key)
   -1    53         else:
   -1    54             self.value += repr(key)
   -1    55             self.cursor += len(repr(key))