Split out panels.py into multiple separate source files.

This commit is contained in:
Dan Helfman
2026-05-26 23:06:36 -07:00
parent ac65e65302
commit 9da6d0f90a
10 changed files with 220 additions and 161 deletions
+11 -3
View File
@@ -5,7 +5,9 @@ import textual.binding
import textual.widgets
import borgmatic.actions.browse.carousel
import borgmatic.actions.browse.configuration_files_list
import borgmatic.actions.browse.logs
import borgmatic.actions.browse.repositories_list
class Browse_app(textual.app.App):
@@ -52,14 +54,20 @@ class Browse_app(textual.app.App):
'''
yield textual.widgets.Header()
yield borgmatic.actions.browse.carousel.Carousel(
[borgmatic.actions.browse.panels.Configuration_files_list(self.configs)]
[
borgmatic.actions.browse.configuration_files_list.Configuration_files_list(
self.configs
)
]
if len(self.configs) > 1
else [
borgmatic.actions.browse.panels.Repositories_list(next(iter(self.configs.values())))
borgmatic.actions.browse.repositories_list.Repositories_list(
next(iter(self.configs.values()))
)
]
)
logs_panel = borgmatic.actions.browse.panels.Logs()
logs_panel = borgmatic.actions.browse.logs.Logs()
yield logs_panel
yield textual.widgets.Footer()
+36
View File
@@ -0,0 +1,36 @@
import contextlib
import os
import textual.binding
import textual.widgets
import borgmatic.actions.browse.bindings
import borgmatic.actions.browse.loading
import borgmatic.actions.browse.paths
import borgmatic.actions.browse.workers
class Archives_list(textual.widgets.OptionList):
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
def __init__(self, config, repository):
self.config = config
self.repository = repository
super().__init__(classes='panel')
self.border_title = '📚 archives'
self.highlighted_option_changed = False
timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
borgmatic.actions.browse.workers.add_repository_archives(
self.app,
archives_list=self,
config=self.config,
repository=self.repository,
timer=timer,
)
def on_option_list_option_highlighted(self, event):
if self.highlighted not in {None, 0}:
self.highlighted_option_changed = True
+23
View File
@@ -0,0 +1,23 @@
import textual.binding
import textual.widgets
OPTION_LIST_BINDINGS = (
*textual.widgets.OptionList.BINDINGS,
textual.binding.Binding(
key='up,k', action='cursor_up', description='scroll up', show=True, priority=True
),
textual.binding.Binding(
key='down,j', action='cursor_down', description='scroll down', show=True, priority=True
),
textual.binding.Binding(
key='pageup', action='page_up', description='page up', show=True, priority=True
),
textual.binding.Binding(
key='pagedown', action='page_down', description='page down', show=True, priority=True
),
textual.binding.Binding(
key='enter', action='select', description='select', show=True, priority=True
),
textual.binding.Binding(key='right,l', action='select', description='select', show=False),
)
+16 -10
View File
@@ -3,8 +3,12 @@ import os
import textual.binding
import textual.containers
import borgmatic.actions.browse.panels
import borgmatic.actions.browse.archives_list
import borgmatic.actions.browse.directory_list
import borgmatic.actions.browse.configuration_files_list
import borgmatic.actions.browse.file_preview
import borgmatic.actions.browse.paths
import borgmatic.actions.browse.repositories_list
def make_next_panel(focused_panel, option_id):
@@ -16,22 +20,24 @@ def make_next_panel(focused_panel, option_id):
If the particular option ID on the focused panel doesn't have a supported next panel, then
return None.
'''
if isinstance(focused_panel, borgmatic.actions.browse.panels.Configuration_files_list):
return borgmatic.actions.browse.panels.Repositories_list(
if isinstance(
focused_panel, borgmatic.actions.browse.configuration_files_list.Configuration_files_list
):
return borgmatic.actions.browse.repositories_list.Repositories_list(
config=focused_panel.configs[option_id]
)
if isinstance(focused_panel, borgmatic.actions.browse.panels.Repositories_list):
return borgmatic.actions.browse.panels.Archives_list(
if isinstance(focused_panel, borgmatic.actions.browse.repositories_list.Repositories_list):
return borgmatic.actions.browse.archives_list.Archives_list(
config=focused_panel.config, repository=focused_panel.repositories[option_id]
)
if isinstance(focused_panel, borgmatic.actions.browse.panels.Archives_list):
return borgmatic.actions.browse.panels.Directory_list(
if isinstance(focused_panel, borgmatic.actions.browse.archives_list.Archives_list):
return borgmatic.actions.browse.directory_list.Directory_list(
config=focused_panel.config, repository=focused_panel.repository, archive_name=option_id
)
if isinstance(focused_panel, borgmatic.actions.browse.panels.Directory_list):
if isinstance(focused_panel, borgmatic.actions.browse.directory_list.Directory_list):
option = focused_panel.get_option(option_id)
if option.prompt.startswith(
@@ -39,7 +45,7 @@ def make_next_panel(focused_panel, option_id):
borgmatic.actions.browse.paths.Path_type.DIRECTORY.value
]
):
return borgmatic.actions.browse.panels.Directory_list(
return borgmatic.actions.browse.directory_list.Directory_list(
focused_panel.config,
focused_panel.repository,
focused_panel.archive_name,
@@ -51,7 +57,7 @@ def make_next_panel(focused_panel, option_id):
borgmatic.actions.browse.paths.Path_type.FILE.value
]
):
return borgmatic.actions.browse.panels.File_preview(
return borgmatic.actions.browse.file_preview.File_preview(
focused_panel.config,
focused_panel.repository,
focused_panel.archive_name,
@@ -0,0 +1,28 @@
import contextlib
import os
import textual.binding
import textual.widgets
import borgmatic.actions.browse.bindings
import borgmatic.actions.browse.loading
import borgmatic.actions.browse.paths
import borgmatic.actions.browse.workers
class Configuration_files_list(textual.widgets.OptionList):
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
def __init__(self, configs):
self.configs = configs
home_directory = os.path.expanduser('~')
super().__init__(
*(
textual.widgets.option_list.Option(unexpanded_path, id=config_path)
for config_path in configs
for unexpanded_path in (config_path.replace(home_directory, '~'),)
),
classes='panel',
)
self.border_title = 'configuration files'
@@ -1,101 +1,15 @@
import contextlib
import logging
import os
import textual.binding
import textual.widgets
import borgmatic.actions.browse.bindings
import borgmatic.actions.browse.loading
import borgmatic.actions.browse.paths
import borgmatic.actions.browse.workers
logger = logging.getLogger('__name__')
OPTION_LIST_BINDINGS = (
*textual.widgets.OptionList.BINDINGS,
textual.binding.Binding(
key='up,k', action='cursor_up', description='scroll up', show=True, priority=True
),
textual.binding.Binding(
key='down,j', action='cursor_down', description='scroll down', show=True, priority=True
),
textual.binding.Binding(
key='pageup', action='page_up', description='page up', show=True, priority=True
),
textual.binding.Binding(
key='pagedown', action='page_down', description='page down', show=True, priority=True
),
textual.binding.Binding(
key='enter', action='select', description='select', show=True, priority=True
),
textual.binding.Binding(key='right,l', action='select', description='select', show=False),
)
class Configuration_files_list(textual.widgets.OptionList):
BINDINGS = OPTION_LIST_BINDINGS
def __init__(self, configs):
self.configs = configs
home_directory = os.path.expanduser('~')
super().__init__(
*(
textual.widgets.option_list.Option(unexpanded_path, id=config_path)
for config_path in configs
for unexpanded_path in (config_path.replace(home_directory, '~'),)
),
classes='panel',
)
self.border_title = 'configuration files'
class Repositories_list(textual.widgets.OptionList):
BINDINGS = OPTION_LIST_BINDINGS
def __init__(self, config):
self.config = config
self.repositories = config['repositories']
super().__init__(
*(
textual.widgets.option_list.Option(label, id=index)
for index, repository in enumerate(self.repositories)
for label in (repository.get('label', repository.get('path')),)
),
classes='panel',
)
self.border_title = '📦 repositories'
class Archives_list(textual.widgets.OptionList):
BINDINGS = OPTION_LIST_BINDINGS
def __init__(self, config, repository):
self.config = config
self.repository = repository
super().__init__(classes='panel')
self.border_title = '📚 archives'
self.highlighted_option_changed = False
timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
borgmatic.actions.browse.workers.add_repository_archives(
self.app,
archives_list=self,
config=self.config,
repository=self.repository,
timer=timer,
)
def on_option_list_option_highlighted(self, event):
if self.highlighted not in {None, 0}:
self.highlighted_option_changed = True
def get_relative_archive_path_components(archive_path, current_directory_path_components):
'''
Given an Archive_path instance and a tuple of path components for the currently browsed
@@ -110,11 +24,14 @@ def get_relative_archive_path_components(archive_path, current_directory_path_co
# If the loaded path doesn't match this directory list's own path, then we don't care about
# it for purposes of displaying this particular directory.
if tuple(archive_path_components[: len(current_directory_path_components)]) != current_directory_path_components:
if (
tuple(archive_path_components[: len(current_directory_path_components)])
!= current_directory_path_components
):
return None
# Strip off the portion of the archive path that matches the directory list's own path.
return archive_path_components[len(current_directory_path_components):]
return archive_path_components[len(current_directory_path_components) :]
def make_directory_list_option(archive_path, archive_path_components):
@@ -144,10 +61,12 @@ def add_archive_paths(
*(
make_directory_list_option(archive_path, archive_path_components)
for archive_path in archive_paths
for archive_path_components in (get_relative_archive_path_components(
archive_path,
directory_list.path_components,
),)
for archive_path_components in (
get_relative_archive_path_components(
archive_path,
directory_list.path_components,
),
)
if archive_path_components
if not archive_path_components[0] in directory_list._id_to_option
),
@@ -168,7 +87,7 @@ def add_archive_paths(
class Directory_list(textual.widgets.OptionList):
BINDINGS = OPTION_LIST_BINDINGS
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
def __init__(self, config, repository, archive_name, path_loaded=None, path_components=None):
self.config = config
@@ -244,57 +163,3 @@ class Directory_list(textual.widgets.OptionList):
def on_option_list_option_highlighted(self, event):
if self.highlighted not in {None, 0}:
self.highlighted_option_changed = True
class File_preview(textual.widgets.RichLog):
BINDINGS = [
*textual.widgets.RichLog.BINDINGS,
textual.binding.Binding(
key='up,k', action='scroll_up', description='scroll up', show=True, priority=True
),
textual.binding.Binding(
key='down,j', action='scroll_down', description='scroll down', show=True, priority=True
),
textual.binding.Binding(
key='pageup', action='page_up', description='page up', show=True, priority=True
),
textual.binding.Binding(
key='pagedown', action='page_down', description='page down', show=True, priority=True
),
]
def __init__(self, config, repository, archive_name, file_path):
self.config = config
self.repository = repository
self.archive_name = archive_name
self.file_path = file_path
super().__init__(classes='panel')
self.border_title = ' '.join(
(
borgmatic.actions.browse.paths.PATH_TYPE_ICONS[
borgmatic.actions.browse.paths.Path_type.FILE.value
],
self.file_path,
'preview',
)
)
self.auto_scroll = False
timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
borgmatic.actions.browse.workers.load_file_preview(
self.app,
file_preview=self,
config=self.config,
repository=self.repository,
archive_name=self.archive_name,
file_path=self.file_path,
timer=timer,
)
class Logs(textual.widgets.RichLog):
def __init__(self):
super().__init__(markup=True, id='logs', classes='panel')
self.border_title = '🪵 logs'
+57
View File
@@ -0,0 +1,57 @@
import contextlib
import os
import textual.binding
import textual.widgets
import borgmatic.actions.browse.loading
import borgmatic.actions.browse.paths
import borgmatic.actions.browse.workers
class File_preview(textual.widgets.RichLog):
BINDINGS = [
*textual.widgets.RichLog.BINDINGS,
textual.binding.Binding(
key='up,k', action='scroll_up', description='scroll up', show=True, priority=True
),
textual.binding.Binding(
key='down,j', action='scroll_down', description='scroll down', show=True, priority=True
),
textual.binding.Binding(
key='pageup', action='page_up', description='page up', show=True, priority=True
),
textual.binding.Binding(
key='pagedown', action='page_down', description='page down', show=True, priority=True
),
]
def __init__(self, config, repository, archive_name, file_path):
self.config = config
self.repository = repository
self.archive_name = archive_name
self.file_path = file_path
super().__init__(classes='panel')
self.border_title = ' '.join(
(
borgmatic.actions.browse.paths.PATH_TYPE_ICONS[
borgmatic.actions.browse.paths.Path_type.FILE.value
],
self.file_path,
'preview',
)
)
self.auto_scroll = False
timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
borgmatic.actions.browse.workers.load_file_preview(
self.app,
file_preview=self,
config=self.config,
repository=self.repository,
archive_name=self.archive_name,
file_path=self.file_path,
timer=timer,
)
+1
View File
@@ -8,6 +8,7 @@ LOADING_DOT_INTERVAL_SECONDS = 0.3
import logging
logger = logging.getLogger('__name__')
+7
View File
@@ -2,6 +2,7 @@ import contextlib
import logging
import textual._context
import textual.widgets
import textual.worker
import borgmatic.logger
@@ -68,3 +69,9 @@ def log_to_widget(logs_widget):
if isinstance(handler, borgmatic.logger.Multi_stream_handler)
)
logger.removeHandler(console_handler)
class Logs(textual.widgets.RichLog):
def __init__(self):
super().__init__(markup=True, id='logs', classes='panel')
self.border_title = '🪵 logs'
@@ -0,0 +1,28 @@
import contextlib
import os
import textual.binding
import textual.widgets
import borgmatic.actions.browse.bindings
import borgmatic.actions.browse.loading
import borgmatic.actions.browse.paths
import borgmatic.actions.browse.workers
class Repositories_list(textual.widgets.OptionList):
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
def __init__(self, config):
self.config = config
self.repositories = config['repositories']
super().__init__(
*(
textual.widgets.option_list.Option(label, id=index)
for index, repository in enumerate(self.repositories)
for label in (repository.get('label', repository.get('path')),)
),
classes='panel',
)
self.border_title = '📦 repositories'