tconbeer / harlequin

The SQL IDE for Your Terminal.
https://harlequin.sh
MIT License
3.8k stars 87 forks source link

Harlequin crashes after pressing `ctrl+g` (goto line) twice #654

Closed tconbeer closed 1 month ago

tconbeer commented 1 month ago

Describe the bug A clear and concise description of what the bug is. With the goto-line input open, press ctrl+g and Harlequin crashes with DuplicateIDs:

trace
╭────────────────────────────────────────────────────────────────── Traceback (most recent call last) ───────────────────────────────────────────────────────────────────╮
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual_textarea/text_editor.py:1270 in action_goto_line                    │
│                                                                                                                                                                        │
│   1267 │   │   │   min_line_number=1,                                                           ╭───────────────────────── locals ──────────────────────────╮          │
│   1268 │   │   │   id="textarea__gotoline_input",                                               │ goto_input = GotoLineInput(id='textarea__gotoline_input') │          │
│   1269 │   │   )                                                                                │       self = CodeEditor(id='buffer-1')                    │          │
│ ❱ 1270 │   │   self._mount_footer_input(input_widget=goto_input)                                ╰───────────────────────────────────────────────────────────╯          │
│   1271 │                                                                                                                                                               │
│   1272 │   def _clear_footer_input(self) -> None:                                                                                                                      │
│   1273 │   │   try:                                                                                                                                                    │
│                                                                                                                                                                        │
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual_textarea/text_editor.py:1288 in _mount_footer_input                 │
│                                                                                                                                                                        │
│   1285 │   │   input_widget.styles.border = "round", self.theme_colors.contrast_text_color      ╭────────────────────────── locals ───────────────────────────╮        │
│   1286 │   │   input_widget.styles.color = self.theme_colors.contrast_text_color                │ input_widget = GotoLineInput(id='textarea__gotoline_input') │        │
│   1287 │   │   self.footer.remove_class("hide")                                                 │         self = CodeEditor(id='buffer-1')                    │        │
│ ❱ 1288 │   │   self.footer.mount(input_widget)                                                  ╰─────────────────────────────────────────────────────────────╯        │
│   1289 │   │   input_widget.focus()                                                                                                                                    │
│   1290 │                                                                                                                                                               │
│   1291 │   def _mount_footer_path_input(self, name: str) -> None:                                                                                                      │
│                                                                                                                                                                        │
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual/widget.py:1015 in mount                                             │
│                                                                                                                                                                        │
│   1012 │   │   else:                                                                            ╭──────────────────────────── locals ─────────────────────────────╮    │
│   1013 │   │   │   parent = self                                                                │         after = None                                            │    │
│   1014 │   │                                                                                    │        before = None                                            │    │
│ ❱ 1015 │   │   mounted = self.app._register(                                                    │  ids_to_mount = ['textarea__gotoline_input']                    │    │
│   1016 │   │   │   parent, *widgets, before=insert_before, after=insert_after                   │  insert_after = None                                            │    │
│   1017 │   │   )                                                                                │ insert_before = None                                            │    │
│   1018                                                                                          │        parent = FooterContainer()                               │    │
│                                                                                                 │          self = FooterContainer()                               │    │
│                                                                                                 │     widget_id = 'textarea__gotoline_input'                      │    │
│                                                                                                 │       widgets = (GotoLineInput(id='textarea__gotoline_input'),) │    │
│                                                                                                 ╰─────────────────────────────────────────────────────────────────╯    │
│                                                                                                                                                                        │
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual/app.py:2760 in _register                                            │
│                                                                                                                                                                        │
│   2757 │   │   │   if not isinstance(widget, Widget):                                                                                                                  │
│   2758 │   │   │   │   raise AppError(f"Can't register {widget!r}; expected a Widget instance")                                                                        │
│   2759 │   │   │   if widget not in self._registry:                                                                                                                    │
│ ❱ 2760 │   │   │   │   self._register_child(parent, widget, before, after)                                                                                             │
│   2761 │   │   │   │   if widget._nodes:                                                                                                                               │
│   2762 │   │   │   │   │   self._register(widget, *widget._nodes, cache=cache)                                                                                         │
│   2763 │   │   │   │   apply_stylesheet(widget, cache=cache)                                                                                                           │
│                                                                                                                                                                        │
│ ╭────────────────────────────────────────────────────────────────────────────── locals ──────────────────────────────────────────────────────────────────────────────╮ │
│ │            after = None                                                                                                                                            │ │
│ │ apply_stylesheet = >                                                                                                                         │ │
│ │           before = None                                                                                                                                            │ │
│ │            cache = {}                                                                                                                                              │ │
│ │           parent = FooterContainer()                                                                                                                               │ │
│ │             self = Harlequin(title='Harlequin', classes={'-dark-mode'})                                                                                            │ │
│ │           widget = GotoLineInput(id='textarea__gotoline_input')                                                                                                    │ │
│ │      widget_list = (GotoLineInput(id='textarea__gotoline_input'),)                                                                                                 │ │
│ │          widgets = (GotoLineInput(id='textarea__gotoline_input'),)                                                                                                 │ │
│ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ │
│                                                                                                                                                                        │
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual/app.py:2708 in _register_child                                      │
│                                                                                                                                                                        │
│   2705 │   │   │   │   # At this point we appear to not be adding before or after,              ╭─────────────────────────── locals ────────────────────────────╮      │
│   2706 │   │   │   │   # or we've got a before/after value that really means                    │  after = None                                                 │      │
│   2707 │   │   │   │   # "please append". So...                                                 │ before = None                                                 │      │
│ ❱ 2708 │   │   │   │   parent._nodes._append(child)                                             │  child = GotoLineInput(id='textarea__gotoline_input')         │      │
│   2709 │   │   │                                                                                │ parent = FooterContainer()                                    │      │
│   2710 │   │   │   # Now that the widget is in the NodeList of its parent, sort out             │   self = Harlequin(title='Harlequin', classes={'-dark-mode'}) │      │
│   2711 │   │   │   # the rest of the admin.                                                     ╰───────────────────────────────────────────────────────────────╯      │
│                                                                                                                                                                        │
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual/_node_list.py:103 in _append                                        │
│                                                                                                                                                                        │
│   100 │   │   │   self._nodes_set.add(widget)                                                                                                                          │
│   101 │   │   │   widget_id = widget.id                                                                                                                                │
│   102 │   │   │   if widget_id is not None:                                                                                                                            │
│ ❱ 103 │   │   │   │   self._ensure_unique_id(widget_id)                                                                                                                │
│   104 │   │   │   │   self._nodes_by_id[widget_id] = widget                                                                                                            │
│   105 │   │   │   self._updates += 1                                                                                                                                   │
│   106                                                                                                                                                                  │
│                                                                                                                                                                        │
│ ╭───────────────────────────────────────────────────────────────────────────── locals ─────────────────────────────────────────────────────────────────────────────╮   │
│ │      self =  │   │
│ │    widget = GotoLineInput(id='textarea__gotoline_input')                                                                                                         │   │
│ │ widget_id = 'textarea__gotoline_input'                                                                                                                           │   │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   │
│                                                                                                                                                                        │
│ /home/tco/.cache/pypoetry/virtualenvs/harlequin-4LobG8aN-py3.8/lib/python3.8/site-packages/textual/_node_list.py:124 in _ensure_unique_id                              │
│                                                                                                                                                                        │
│   121 │                                                                                                                                                                │
│   122 │   def _ensure_unique_id(self, widget_id: str) -> None:                                                                                                         │
│   123 │   │   if widget_id in self._nodes_by_id:                                                                                                                       │
│ ❱ 124 │   │   │   raise DuplicateIds(                                                                                                                                  │
│   125 │   │   │   │   f"Tried to insert a widget with ID {widget_id!r}, but a widget {self._no                                                                         │
│   126 │   │   │   │   "already exists with that ID in this list of children. "                                                                                         │
│   127 │   │   │   │   "The children of a widget must have unique IDs."                                                                                                 │
│                                                                                                                                                                        │
│ ╭───────────────────────────────────────────────────────────────────────────── locals ─────────────────────────────────────────────────────────────────────────────╮   │
│ │      self =  │   │
│ │ widget_id = 'textarea__gotoline_input'                                                                                                                           │   │
│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯   │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
DuplicateIds: Tried to insert a widget with ID 'textarea__gotoline_input', but a widget GotoLineInput(id='textarea__gotoline_input') already exists with that ID in this
list of children. The children of a widget must have unique IDs.

Contributing Are you interested in contributing a fix?

tconbeer commented 1 month ago

upstream fix: https://github.com/tconbeer/textual-textarea/pull/286