The Drives Dialog System is a unified interface for selecting and navigating to different storage locations in XeFM, including local filesystem directories and remote S3 buckets. This system enhances XeFM’s navigation capabilities by offering quick access to commonly used storage locations through a clean, consistent interface.
| Key | Action |
|---|---|
↑/↓ |
Navigate up/down through drives |
Page Up/Down |
Navigate by pages |
Home/End |
Jump to first/last drive |
Type |
Filter drives by text |
Enter |
Select and navigate to drive |
ESC |
Cancel and close dialog |
The Drives Dialog follows XeFM’s modular dialog architecture with clean separation of concerns:
class DriveEntry:
def __init__(self, name: str, path: str, description: str = "", icon: str = "💾")
@property
def display_name(self) -> str
@property
def full_description(self) -> str
Represents individual storage locations with:
s3://bucket-name/)class DrivesDialog(BaseListDialog):
def __init__(self, config)
def show(self)
def exit(self)
def handle_input(self, key)
def draw(self, stdscr, safe_addstr_func)
def get_selected_drive(self) -> Optional[DriveEntry]
Main dialog class extending BaseListDialog with:
class DrivesDialogHelpers:
@staticmethod
def navigate_to_drive(file_manager, drive_entry: DriveEntry)
@staticmethod
def get_local_drives() -> List[DriveEntry]
@staticmethod
def get_s3_drives() -> List[DriveEntry]
Static helper methods for:
def _scan_s3_buckets_thread(self):
"""Background thread for S3 bucket discovery"""
try:
# Discover S3 buckets using boto3
s3_drives = DrivesDialogHelpers.get_s3_drives()
# Thread-safe update of drive list
with self._drives_lock:
self.s3_drives = s3_drives
self.drives_loaded = True
self.content_changed = True
except Exception as e:
# Handle errors gracefully
self._handle_s3_error(e)
Features:
def _get_loading_indicator(self) -> str:
"""Animated loading indicator for S3 scanning"""
if not self.scanning_s3:
return ""
frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
frame_index = (time.time() * 4) % len(frames)
return frames[int(frame_index)]
Provides smooth visual feedback during background operations.
def _handle_s3_error(self, error):
"""Handle S3 errors with appropriate user feedback"""
if isinstance(error, NoCredentialsError):
self._add_s3_placeholder("S3 (No Credentials)",
"Configure AWS credentials to access S3 buckets")
elif isinstance(error, ClientError):
self._add_s3_placeholder("S3 (Access Error)",
f"Error accessing S3: {error}")
else:
self._add_s3_placeholder("S3 (Error)",
"Unable to load S3 buckets")
def _filter_drives(self, filter_text: str) -> List[DriveEntry]:
"""Efficient case-insensitive filtering of drives"""
if not filter_text:
return self.all_drives
filter_lower = filter_text.lower()
return [drive for drive in self.all_drives
if filter_lower in drive.name.lower()
or filter_lower in drive.path.lower()
or filter_lower in drive.description.lower()]
# In FileManager.__init__()
self.drives_dialog = DrivesDialog(self.config)
# In FileManager.run() main loop
elif self.is_key_for_action(key, 'drives'):
self.show_drives_dialog()
# Dialog input handling
if self.drives_dialog.mode:
result = self.drives_dialog.handle_input(key)
if result == 'select':
selected_drive = self.drives_dialog.get_selected_drive()
if selected_drive:
DrivesDialogHelpers.navigate_to_drive(self, selected_drive)
self.drives_dialog.exit()
elif result == 'cancel':
self.drives_dialog.exit()
# In main draw loop
def _draw_dialogs_if_needed(self):
if self.drives_dialog.mode:
self.drives_dialog.draw(self.stdscr, self.safe_addstr)
@staticmethod
def navigate_to_drive(file_manager, drive_entry: DriveEntry):
"""Navigate to selected drive in active pane"""
try:
# Update active pane path
active_pane = file_manager.get_active_pane()
active_pane['path'] = Path(drive_entry.path)
active_pane['selected_files'] = set()
active_pane['scroll_offset'] = 0
# Refresh pane content
file_manager.refresh_files()
file_manager.needs_full_redraw = True
# User feedback
file_manager.show_status(f"Navigated to: {drive_entry.name}")
except Exception as e:
file_manager.show_error(f"Failed to navigate to {drive_entry.name}: {e}")
Default configuration in xefm/_config.py:
KEY_BINDINGS = {
# ... other bindings ...
'drives': ['d', 'D'], # Show drives/storage selection dialog
}
DRIVE_LOCATIONS)The rows above the mounted volumes are configurable (issue #356); everything
below them — Windows drive letters, /Volumes, /media, /mnt, the hosts in
~/.ssh/config, S3 buckets — is always discovered, never configured.
DRIVE_LOCATIONS = None # built-in set (default)
DRIVE_LOCATIONS = [] # no fixed rows at all — only what is discovered
DRIVE_LOCATIONS = [{'name': 'Work', 'path': '~/work'}]
config.get_drive_locations() resolves it, and XeFMApp._local_drives() starts
from what it returns. The resolution is deliberately a replacement, not a
filter: a user who wants Documents gone says what they do want, rather than
naming what to subtract.
Three rules live in get_drive_locations():
None means the built-in set (_default_drive_locations()): Home, Root on
POSIX only — on Windows the drive letters already cover it — and whichever of
Documents / Downloads / Desktop exist._REMOTE_SCHEMES: ssh://, s3://, …)
is passed through unprobed. Path.exists() on one would open a connection on
the UI thread while the picker is being built — the picker’s job is to offer
a connection, not to make one.The drives dialog respects existing XeFM configuration:
d or D to open the drives dialogEnter to navigate to selected driveESC to cancel and close dialogtest/test_drives_dialog.py)test/test_drives_dialog_integration.py)All tests pass successfully:
The drives dialog is automatically available when XeFM is installed. For S3 functionality:
# Install AWS SDK
pip install boto3
# Configure AWS credentials
aws configure
# or set environment variables
export AWS_ACCESS_KEY_ID=your_access_key
export AWS_SECRET_ACCESS_KEY=your_secret_key
export AWS_DEFAULT_REGION=us-west-2
Symptoms: No S3 buckets appear in the drives dialog Solutions:
aws s3 lsSymptoms: Dialog takes long time to show S3 buckets Causes:
Symptoms: Some drives show access errors Causes:
Enable debug logging to troubleshoot issues:
Common error messages and their meanings:
class DriveEntry:
def __init__(self, name: str, path: str, description: str = "", icon: str = "💾")
@property
def display_name(self) -> str
"""Get formatted display name with icon"""
@property
def full_description(self) -> str
"""Get complete description including path"""
class DrivesDialog(BaseListDialog):
def __init__(self, config)
"""Initialize drives dialog with configuration"""
def show(self)
"""Show the drives dialog and start S3 scanning"""
def exit(self)
"""Exit dialog and cleanup resources"""
def handle_input(self, key) -> str
"""Handle keyboard input, returns 'select', 'cancel', or None"""
def get_selected_drive(self) -> Optional[DriveEntry]
"""Get currently selected drive entry"""
class DrivesDialogHelpers:
@staticmethod
def navigate_to_drive(file_manager, drive_entry: DriveEntry)
"""Navigate XeFM to the specified drive"""
@staticmethod
def get_local_drives() -> List[DriveEntry]
"""Get list of local filesystem drives"""
@staticmethod
def get_s3_drives() -> List[DriveEntry]
"""Get list of accessible S3 buckets"""
The XeFM Drives Dialog System successfully enhances XeFM’s navigation capabilities by providing a unified, user-friendly interface for accessing both local and remote storage locations. The implementation follows XeFM’s established patterns, includes comprehensive error handling, and provides a solid foundation for future enhancements.
The system is production-ready and provides immediate value to XeFM users who work with both local files and cloud storage, while maintaining the performance and reliability standards expected from XeFM.