summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrett Curran <brettjcurran@gmail.com>2026-02-12 13:12:07 +1100
committerBrett Curran <brettjcurran@gmail.com>2026-02-12 13:12:07 +1100
commitc6ea6efcbb9e1558d32f4a584d574ab301df41c4 (patch)
tree5ddf81c09f7757c2184ddf0e26f65fe4790eb6a1
parentb1cff893077f8042c57fa387d057e644877ccc88 (diff)
fix vim-like navigation in panes
-rw-r--r--pyproject.toml22
-rw-r--r--tui.py68
2 files changed, 44 insertions, 46 deletions
diff --git a/pyproject.toml b/pyproject.toml
index b53adf9..152e07a 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,3 +7,25 @@ requires-python = ">=3.12"
dependencies = [
"textual>=7.5.0",
]
+
+[tool.bumpversion]
+current_version = "0.1.0"
+parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
+serialize = ["{major}.{minor}.{patch}"]
+search = "{current_version}"
+replace = "{new_version}"
+regex = false
+ignore_missing_version = false
+ignore_missing_files = false
+tag = true
+sign_tags = false
+tag_name = "v{new_version}"
+tag_message = "Bump version: {current_version} → {new_version}"
+allow_dirty = false
+commit = true
+message = "Bump version: {current_version} → {new_version}"
+moveable_tags = []
+commit_args = ""
+setup_hooks = []
+pre_commit_hooks = []
+post_commit_hooks = []
diff --git a/tui.py b/tui.py
index 1c84892..6afa075 100644
--- a/tui.py
+++ b/tui.py
@@ -8,18 +8,6 @@ import os
import subprocess
-def get_git_version():
- try:
- # git describe --tags --always --dirty
- # Returns things like: "v1.0.2-4-g9a2b3c" or "v1.0.2"
- return subprocess.check_output(
- ["git", "describe", "--tags", "--always", "--dirty"],
- stderr=subprocess.DEVNULL
- ).decode("utf-8").strip()
- except (subprocess.CalledProcessError, FileNotFoundError):
- return "dev"
-
-
# --- MOCK DATA GENERATOR (Creates fake files for testing) ---
def create_mock_files():
root = Path("mock_campaign")
@@ -47,39 +35,14 @@ def create_mock_files():
class CampaignTree(DirectoryTree):
"""A DirectoryTree with Vim-like navigation."""
- # TODO: Bindings do not actually work to navigate the tree.
BINDINGS = [
- Binding("h", "collapse_or_parent", "Collapse / Up"),
- Binding("l", "expand_node", "Expand"),
- # j and k are built-in to DirectoryTree for navigation, so we don't need to add them
+ # Map Vim keys to standard Tree actions
+ Binding("j", "cursor_down", "Down", show=False),
+ Binding("k", "cursor_up", "Up", show=False),
+ Binding("h", "cursor_left", "Collapse / Parent", show=True),
+ Binding("l", "cursor_right", "Expand / Child", show=True),
]
- def action_collapse_or_parent(self):
- """Collapse node or jump to parent."""
- node = self.cursor_node
- if not node:
- return
-
- if node.is_expanded:
- node.collapse()
- elif node.parent:
- # Jump to parent logic
- target_node = node.parent
- # Find the line number of the parent
- current_line = self.cursor_line
- while current_line > 0:
- current_line -= 1
- if self.get_node_at_line(current_line) == target_node:
- self.cursor_line = current_line
- self.scroll_to_line(current_line)
- break
-
- def action_expand_node(self):
- """Expand the current node."""
- node = self.cursor_node
- if node and node.allow_expand and not node.is_expanded:
- node.expand()
-
class FileTable(DataTable):
"""A DataTable with custom file selection actions."""
@@ -91,6 +54,8 @@ class FileTable(DataTable):
BINDINGS = [
Binding("space", "toggle_select", "Select/Deselect"),
Binding("a", "toggle_all", "Select All"),
+ Binding("j", "cursor_down", "Down", show=False),
+ Binding("k", "cursor_up", "Up", show=False),
# Category Shortcuts
Binding("s", "set_category('Scenes')", "Set: Scenes"),
Binding("t", "set_category('Tokens')", "Set: Tokens"),
@@ -222,6 +187,17 @@ class PublisherApp(App):
("q", "quit", "Quit"),
]
+ def get_git_version(self):
+ try:
+ # git describe --tags --always --dirty
+ # Returns things like: "v1.0.2-4-g9a2b3c" or "v1.0.2"
+ return subprocess.check_output(
+ ["git", "describe", "--tags", "--always", "--dirty"],
+ stderr=subprocess.DEVNULL
+ ).decode("utf-8").strip()
+ except (subprocess.CalledProcessError, FileNotFoundError):
+ return "dev"
+
def compose(self) -> ComposeResult:
"""Create child widgets for the app."""
yield Header(show_clock=True)
@@ -233,7 +209,7 @@ class PublisherApp(App):
yield Static(" Directory Browser", classes="pane-header")
# Start at current directory or mock directory
start_path = "./mock_campaign" if os.path.exists("./mock_campaign") else "."
- yield DirectoryTree(start_path, id="tree_view")
+ yield CampaignTree(start_path, id="tree_view")
# Right Pane: Data Table
with Container(id="right_pane"):
@@ -248,10 +224,10 @@ class PublisherApp(App):
def on_mount(self) -> None:
"""Called when app starts."""
- version_str = get_git_version()
- self.title = f"FVTT PUBLISH v{version_str}"
+ version_str = self.get_git_version()
+ self.title = f"FVTT PUBLISH {version_str}"
- table = self.query_one(DataTable)
+ table = self.query_one(FileTable)
table.cursor_type = "row"
# DEFINING EXPLICIT KEYS HERE IS THE MAGIC SAUCE