diff --git a/CHANGELOG.md b/CHANGELOG.md
index 30f8115..a00a968 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,9 @@
## Next version
-Nothing yet
+- Add demo gif to readme
+- Fix indentation of multi-line messages
+- Stop using dataclass (for backwards compatibility with Python 3.6)
## 1.0.0 (2019-06-21)
diff --git a/README.md b/README.md
index 696f64f..e9b3676 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,8 @@
A TUI client for [euphoria.io](https://euphoria.io)
+
+
## Installation
Ensure that you have at least Python 3.7 installed.
diff --git a/bowl/config.py b/bowl/config.py
index a25f599..19fb1ec 100644
--- a/bowl/config.py
+++ b/bowl/config.py
@@ -1,4 +1,3 @@
-from dataclasses import dataclass, field
from enum import Enum, auto
from typing import Any, Callable, Dict, Iterable, List, Optional, Tuple
@@ -62,12 +61,17 @@ class Kind(Enum):
Condition = Callable[[Any], bool]
-@dataclass
class Option:
- kind: Kind
- default: Any
- conditions: Iterable[Tuple[Condition, str]] = field(default_factory=list)
+ def __init__(self,
+ kind: Kind,
+ default: Any,
+ conditions: Iterable[Tuple[Condition, str]] = frozenset(),
+ ) -> None:
+
+ self.kind = kind
+ self.default = default
+ self.conditions = conditions
def check_valid(self, value: Any) -> None:
if not self.kind.matches(value):
diff --git a/bowl/euphoria/euph_renderer.py b/bowl/euphoria/euph_renderer.py
index c999a7d..00421c0 100644
--- a/bowl/euphoria/euph_renderer.py
+++ b/bowl/euphoria/euph_renderer.py
@@ -123,7 +123,7 @@ class EuphRenderer(CursorRenderer):
right = AT(self._surround_right, attributes=self._surround_attrs)
nick_str = left + nick + right + AT(" ")
- nick_spaces = AT(" " * len(nick))
+ nick_spaces = AT(" " * len(nick_str))
content = self._filter_unicode(message.content)
lines = []
diff --git a/demo.gif b/demo.gif
new file mode 100644
index 0000000..c306d8f
Binary files /dev/null and b/demo.gif differ
diff --git a/todo.txt b/todo.txt
new file mode 100644
index 0000000..6f4705b
--- /dev/null
+++ b/todo.txt
@@ -0,0 +1,37 @@
+- config
+ x colors
+ - key bindings
+- documentation (especially of the config)
+
+- profiling/optimisation
+
+- detail mode
+- fold threads
+- nick list
+- better key bindings/controls
+- center cursor on screen (after scrolling the view without scrolling the cursor)
+- mouse support
+- searching for messages
+- better message editing when the screen is full
+- detect when the dimensions are too small (meta width etc.) and display warning
+- green "unread message" markers
+- highlight things in messages
+ - offline log browsing
+ - @mentions
+ - &rooms
+ - https://links
+ - :emojis:
+ - /me s
+- word wrapping for messages
+- multi-room support
+- db backend
+ - download room log
+ - auto repair gaps in log
+
+x robust starting script
+x install via pip from github
+ x runnable script
+x parse command-line parameters
+x nick list
+x room_widget refactor
+x save cookies
diff --git a/tree_display.py b/tree_display.py
deleted file mode 100644
index 2d9a4af..0000000
--- a/tree_display.py
+++ /dev/null
@@ -1,295 +0,0 @@
-# Element supply of some sort
-# Dict-/map-like
-# Tree structure
-# ↓
-# List of already formatted elements
-# Each with a line height, indentation, ...
-# List structure
-# ↓
-# Messages and UI elements rendered to lines
-# with meta-information, links/ids
-# List structure, but on lines, not individual messages
-
-class Element:
- pass
-
-class ElementSupply:
- pass
-
-class TreeDisplay:
- """
- Message line coordinates:
-
- n - Highest message
- ...
- 1 - Higher message
- 0 - Lowest message
-
- Screen/line coordinates:
-
- h-1 - First line
- h-2 - Second line
- ...
- 1 - Second to last line
- 0 - Last line
-
- Terms:
-
-
- | ...
- | ... (above)
- | ...
- |
- | | ...
- | | | ... |
- | ...
- | ... (below)
- | ...
-
- or
-
-
- | ...
- | ... (above)
- | ...
- |
- | ...
- | ... (below)
- | ...
-
- The stem is a child of the base. The anchor is a direct or indirect child
- of the stem, or it is the stem itself.
-
- The base id may also be None (the implicit parent of all top-level
- messages in a room)
- """
-
- def __init__(self, window: Any) -> None:
- self.window = window
-
- self._anchor_id = None
- # Position of the formatted anchor's uppermost line on the screen
- self._anchor_screen_pos = 0
-
-
- def render(self) -> None:
- """
- Intermediate structures:
- - Upwards and downwards list of elements + focused element
- - Upwards and downwards list of rendered elements + focused element
- - List of visible lines (saved and used for mouse clicks etc.)
-
- Steps of rendering:
- 1. Load all necessary elements
- 2. Render all messages with indentation
- 3. Compile lines
-
- Steps of advanced rendering:
- 1. Load focused element + render
- 2. Load tree of focused element + render
- 3. Load trees above and below + render, as many as necessary
- 4. While loading and rendering trees, auto-collapse
- 5. Move focus if focused element was hidden in an auto-collapse
- ...?
- """
-
- # Step 1: Find and render the tree the anchor is in.
-
- stem_id = self._supply.find_stem_id(self._anchor_id,
- base=self._base_id)
-
- tree = self._supply.get_tree(stem_id)
- # The render might modify self._anchor_id, if the original anchor can't
- # be displayed.
- self._render_tree(tree)
-
- above, anchor, below = self._split_at_anchor(tree)
-
- # Step 2: Add more trees above and below, until the screen can be
- # filled or there aren't any elements left in the store.
-
- # h_win = 7
- # 6 | <- h_above = 3
- # 5 |
- # 4 |
- # 3 | <- anchor, self._anchor_screen_pos = 3, anchor.height = 2
- # 2 |
- # 1 | <- h_below = 2
- # 0 |
- #
- # 7 - 3 - 1 = 3 -- correct
- # 3 - 2 + 1 = 2 -- correct
-
- height_window = None # TODO
-
- # All values are converted to zero indexed values in the calculations
- height_above = (height_window - 1) - self._anchor_screen_pos
- height_below = self._anchor_screen_pos - (anchor.height - 1)
-
- self._extend(above, height_above, base=self._base_id)
- self._extend(below, height_below, base=self._base_id)
-
- self._lines = self._render_to_lines(above, anchor, below)
- self._update_window(self._lines)
-
-# TreeDisplay plan(s):
-#
-# [ ] 1. Render a basic tree thing from an ElementSupply
-# [ ] 1.1. Take/own a curses window
-# [ ] 1.2. Keep track of the text internally
-# [ ] 1.3. Retrieve elements from an ElementSupply
-# [ ] 1.4. Render elements to text depending on width of curses window
-# [ ] 1.5. Do indentation
-# [ ] 1.6. Use "..." where a thing can't be rendered
-# [ ] 2. Scroll and anchor to messages
-# [ ] 2.1. Listen to key presses
-# [ ] 2.2. Scroll up/down single lines
-# [ ] 2.3. Render starting from the anchor
-# [ ] 2.4. Some sort of culling, but preserve CONSISTENCY!
-# [ ] 3. Focus on single message
-# [ ] 3.1. Keep track of focused message
-# [ ] 3.2. Move focused message
-# [ ] 3.3. Keep message visible on screen
-# [ ] 3.4. Set anchor to focus when focus is visible
-# [ ] 3.5. Find anchor solution for when focus is offscreen
-# [ ] 4. Collapse element threads
-# [ ] 4.1. Collapse thread at any element
-# [ ] 4.2. Auto-collapse threads when they can't be displayed
-# [ ] 4.3. Focus collapsed messages
-# [ ] 4.4. Move focus when a hidden message would have focus
-# [ ] 5. Interaction with elements
-# [ ] 5.1. Forward key presses
-# [ ] 5.2. Mouse clicks + message attributes
-# [ ] 5.3. Element visibility
-# [ ] 5.4. Request more elements when the top of the element supply is hit
-# [ ] 5.5. ... and various other things
-
-# STRUCTURE
-#
-# No async!
-#
-# The TreeView "owns" and completely fills one curses window.
-#
-# When rendering things, the TreeDisplay takes elements from the ElementSupply
-# as needed. This should be a fast operation.
-#
-# When receiving key presses, the ones that are not interpreted by the TreeView
-# are passed onto the currently focused element (if any).
-#
-# When receiving mouse clicks, the clicked-on element is focused and then the
-# click and attributes of the clicked character are passed onto the focused
-# element.
-#
-# (TODO: Notify focused elements? Make "viewed/new" state for elements
-# possible?)
-#
-#
-#
-# DESIGN PRINCIPLES
-#
-# Layout: See below
-#
-# Color support: Definitely.
-# No-color-mode: Not planned.
-# => Colors required.
-
-# The tree display can display a tree-like structure of elements.
-#
-# Each element consists of:
-# 1. a way to display the element
-# 2. a way to forward key presses to the element
-# 3. element-specific attributes (Attributes), including:
-# 3.1 "id", the element's hashable id
-# 3.2 optionally "parent_id", the element's parent's hashable id
-#
-# (TODO: A way to notify the element that it is visible?)
-#
-# (TODO: Jump to unread messages, mark messages as read, up/down arrows like
-# instant, message jump tags?)
-#
-# (TODO: Curses + threading/interaction etc.?)
-#
-#
-#
-# LAYOUT
-#
-# A tree display's basic structure is something like this:
-#
-#
-# |
-# | |
-# | |
-# |
-# |
-# | |
-# | | |
-# |
-#
-# |
-#
-# It has an indentation string ("| " in the above example) that is prepended to
-# each line according to its indentation. (TODO: Possibly add different types
-# of indentation strings?)
-#
-# In general, "..." is inserted any time a message or other placeholder can't
-# be displayed. (TODO: If "..." can't be displayed, it is shortened until it
-# can be displayed?)
-#
-# Elements can be collapsed. Collapsed elements are displayed as "+ ()"
-# where is the number of elements in the hidden subtree.
-#
-# If an element is so far right that it can't be displayed, the tree display
-# first tries to collapse the tree. If the collapsed message can't be displayed
-# either, it uses "..." as mentioned above.
-#
-#
-# |
-# | |
-# | |
-# |
-# | + (3)
-# |
-#
-# |
-# | |
-# | | |
-# | | | | ...
-#
-#
-#
-# NAVIGATION
-#
-# For navigation, the following movements/keys are used (all other key presses
-# are forwarded to the currently selected element, if there is one):
-#
-# LEFT (left arrow, h): move to the selected element's parent
-#
-# RIGHT (right arrow, l): move to the selected element's first child
-#
-# UP (up arrow, k): move to the element visually below the selected element
-#
-# DOWN (down arrow, j): move to the element visually above the selected element
-#
-# Mod + LEFT: move to the selected element's previous sibling, if one exists
-#
-# Mod + RIGHT: move to the selected element's next sibling, if one exists
-#
-# Mod + UP: scroll up by scroll step
-#
-# Mod + DOWN: scroll down by scroll step
-#
-#
-# CURSES
-#
-# Main thread:
-# - async
-# - yaboli
-# - curses: non-blocking input
-# - curses: update visuals
-# - run editor in async variant of subprocess or separate thread
-#
-#
-#
-# STRUCTURE
-#
-# ???