railmux 0.4.2.dev6__tar.gz → 0.4.2.dev8__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {railmux-0.4.2.dev6/src/railmux.egg-info → railmux-0.4.2.dev8}/PKG-INFO +1 -1
- railmux-0.4.2.dev8/src/railmux/__init__.py +1 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/fast_display_server.py +31 -6
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/transcript.py +76 -21
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8/src/railmux.egg-info}/PKG-INFO +1 -1
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fast_display_server.py +16 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_transcript.py +52 -7
- railmux-0.4.2.dev6/src/railmux/__init__.py +0 -1
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/LICENSE +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/MANIFEST.in +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/README.md +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/pyproject.toml +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/setup.cfg +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/__main__.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/atomic_file.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/background_index.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/cli.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/codex_index.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/config.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/config_cli.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/diagnostic_contract.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/diagnostics.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/discovery.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/display_transport.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/entrypoint.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/fast_display_client.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/fast_display_history.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/fast_display_input.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/fast_display_protocol.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/favorites.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/fuzzy.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/help_workspace.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/image_paste.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/launcher.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/legacy_sessions.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/local_clipboard.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/local_open.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/models.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/modes.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/mouse_manager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/orphan_marker.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/pane_surface.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/path_codec.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/preview_pager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/project_favorites.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/provider_paths.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/release_version.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/remote_config.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/renames.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/restart_state.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/runtime_config.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/scroll_agent.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/scroll_manager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/selection_isolation.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/self_update.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/session_cache.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/session_index.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/session_lease.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/setting_contracts.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/settings.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ssh_args.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ssh_compat.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ssh_display_diagnostics.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ssh_doctor.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ssh_preflight.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/system_deps.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/terminal_screen.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/terminal_status.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/tmux_binding_manager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/tmux_capabilities.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/tmux_ctl.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/tmux_health.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/tmux_server.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/tool_panes.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/__init__.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/_widgets.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/app.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/keymap.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/modals.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/projects_pane.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/running_pane.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/sessions_pane.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/sidebar.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/statusbar.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/ui/workspace.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_attach_relay.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_bootstrap.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_install_log.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_msys2.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_pacman.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_paths.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_tmux_lifecycle.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux/windows_ui_transition.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux.egg-info/SOURCES.txt +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux.egg-info/dependency_links.txt +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux.egg-info/entry_points.txt +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux.egg-info/requires.txt +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/src/railmux.egg-info/top_level.txt +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/app_test_harness.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_agent_workspace.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_app_codex_placeholder.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_app_quit.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_app_restart_restore.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_app_running_recovery.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_atomic_file.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_background_index.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_claude_continuation.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_cli.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_code_map.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_codex_delete.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_codex_index.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_codex_lineage.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_codex_transcript.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_config.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_config_cli.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_denested_transport_benchmark.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_diagnostics.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_discovery.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_display_transport.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fast_display_bootstrap.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fast_display_history.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fast_display_protocol.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fast_display_selection.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fast_display_terminal.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_focus_highlight.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fullscreen_binding.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_fuzzy.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_help_agent.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_help_workspace.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_history_cleanup.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_image_paste.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_keymap.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_launcher.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_layout_profile.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_legacy_sessions.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_local_clipboard.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_local_open.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_modals.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_mode_selection.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_modes.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_mouse_manager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_new_project.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_options.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_orphan_recovery.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_pane_surface.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_path_codec.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_preview_pager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_project_favorites.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_projects_pane.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_provider_paths.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_release_notes.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_release_version.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_release_workflow.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_remote_config.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_renames.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_restart_state.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_running_pane.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_running_sort.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_runtime_config.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_scroll_agent.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_scroll_manager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_selection_isolation.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_self_update.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_session_cache.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_session_index.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_session_lease.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_sessions_pane.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_setting_contracts.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_settings.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_sidebar.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_ssh_args.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_ssh_compat.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_ssh_display_benchmark.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_ssh_display_diagnostics.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_ssh_doctor.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_status.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_statusbar.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_system_deps.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_terminal_size.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_terminal_status.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_termux_local_touch.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_binding_manager.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_capabilities.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_ctl.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_health.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_integration.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_server.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tmux_status.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_tool_panes.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_utf8_state.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_web_demo_recorder.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_wheel_smoke.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_widgets.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_attach_relay.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_bootstrap.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_install_log.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_msys2.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_pacman.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_paths.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_synchronized_screen.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_tmux_lifecycle.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_ui_transition.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_windows_wrapper_contract.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tests/test_yolo_prompt.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tools/denested_transport_benchmark.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tools/release_notes.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tools/wheel_smoke.py +0 -0
- {railmux-0.4.2.dev6 → railmux-0.4.2.dev8}/tools/windows_archive_smoke.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.4.2.dev8"
|
|
@@ -89,6 +89,7 @@ from railmux.terminal_screen import (
|
|
|
89
89
|
HyperlinkTrackingStream,
|
|
90
90
|
Osc52ClipboardDecoder as _Osc52ClipboardDecoder,
|
|
91
91
|
ScreenState as _ScreenState,
|
|
92
|
+
_safe_hyperlink,
|
|
92
93
|
build_screen_update,
|
|
93
94
|
extended_pyte as _extended_pyte,
|
|
94
95
|
render_rows,
|
|
@@ -1616,11 +1617,17 @@ def _read_transcript_tail(fd: int) -> tuple[str, bool]:
|
|
|
1616
1617
|
def _wrap_transcript_rows(
|
|
1617
1618
|
pyte: object, text: str, width: int
|
|
1618
1619
|
) -> tuple[tuple[bytes, ...], bool, int]:
|
|
1619
|
-
"""Wrap allowlisted transcript ANSI into independently paintable rows.
|
|
1620
|
+
"""Wrap allowlisted transcript ANSI into independently paintable rows.
|
|
1621
|
+
|
|
1622
|
+
SGR styles and HTTP(S) OSC 8 links are kept; a link that crosses a row
|
|
1623
|
+
break is closed at the row end and reopened on the next row, as
|
|
1624
|
+
:func:`render_rows` emits links for captured screen rows.
|
|
1625
|
+
"""
|
|
1620
1626
|
rows: deque[bytes] = deque(maxlen=MAX_HISTORY_LINES)
|
|
1621
1627
|
row = bytearray(b"\033[0m")
|
|
1622
1628
|
column = 0
|
|
1623
1629
|
active: list[bytes] = []
|
|
1630
|
+
link = b""
|
|
1624
1631
|
dropped = False
|
|
1625
1632
|
total_rows = 0
|
|
1626
1633
|
|
|
@@ -1629,12 +1636,28 @@ def _wrap_transcript_rows(
|
|
|
1629
1636
|
total_rows += 1
|
|
1630
1637
|
if len(rows) == rows.maxlen:
|
|
1631
1638
|
dropped = True
|
|
1632
|
-
rows.append(bytes(row) + b"\033[0m")
|
|
1633
|
-
row = bytearray(b"\033[0m" + b"".join(active))
|
|
1639
|
+
rows.append(bytes(row) + (_LINK_END if link else b"") + b"\033[0m")
|
|
1640
|
+
row = bytearray(b"\033[0m" + b"".join(active) + link)
|
|
1634
1641
|
column = 0
|
|
1635
1642
|
|
|
1636
|
-
for match in re.finditer(
|
|
1643
|
+
for match in re.finditer(
|
|
1644
|
+
r"\x1b\[[0-9;]*m|\x1b\]8;;([^\x1b]*)\x1b\\|[^\x1b]+", text
|
|
1645
|
+
):
|
|
1637
1646
|
token = match.group(0)
|
|
1647
|
+
if token.startswith("\x1b]"):
|
|
1648
|
+
target = match.group(1)
|
|
1649
|
+
if target and _safe_hyperlink(target.encode("utf-8")) is None:
|
|
1650
|
+
continue
|
|
1651
|
+
encoded = token.encode("utf-8")
|
|
1652
|
+
if link and target:
|
|
1653
|
+
row.extend(_LINK_END)
|
|
1654
|
+
if target:
|
|
1655
|
+
link = encoded
|
|
1656
|
+
row.extend(encoded)
|
|
1657
|
+
elif link:
|
|
1658
|
+
link = b""
|
|
1659
|
+
row.extend(_LINK_END)
|
|
1660
|
+
continue
|
|
1638
1661
|
if token.startswith("\x1b["):
|
|
1639
1662
|
encoded = token.encode("ascii")
|
|
1640
1663
|
params = token[2:-1].split(";")
|
|
@@ -1672,7 +1695,7 @@ def _wrap_transcript_rows(
|
|
|
1672
1695
|
finish()
|
|
1673
1696
|
row.extend(char.encode("utf-8"))
|
|
1674
1697
|
column += max(0, cell_width)
|
|
1675
|
-
if column or len(row) > len(b"\033[0m" + b"".join(active)):
|
|
1698
|
+
if column or len(row) > len(b"\033[0m" + b"".join(active) + link):
|
|
1676
1699
|
finish()
|
|
1677
1700
|
return tuple(rows), dropped, total_rows
|
|
1678
1701
|
|
|
@@ -1750,7 +1773,9 @@ def _transcript_rows(
|
|
|
1750
1773
|
os.close(fd)
|
|
1751
1774
|
|
|
1752
1775
|
|
|
1753
|
-
|
|
1776
|
+
_LINK_END = b"\033]8;;\033\\"
|
|
1777
|
+
_OVERLAP_STYLE_RE = re.compile(
|
|
1778
|
+
rb"\x1b\[[0-9;]*m|\x1b\]8;;[^\x1b]*\x1b\\")
|
|
1754
1779
|
_OVERLAP_SPACE_RE = re.compile(r"\s+")
|
|
1755
1780
|
_OVERLAP_ANCHOR_CHARS = 12
|
|
1756
1781
|
_OVERLAP_SINGLE_ANCHOR_CHARS = 24
|
|
@@ -13,6 +13,7 @@ import os
|
|
|
13
13
|
import re
|
|
14
14
|
import sys
|
|
15
15
|
from pathlib import Path
|
|
16
|
+
from urllib.parse import urlsplit
|
|
16
17
|
|
|
17
18
|
# ── ANSI styles ──────────────────────────────────────────────────────────
|
|
18
19
|
BOLD = "\033[1m"
|
|
@@ -28,6 +29,7 @@ ITALIC = "\033[3m"
|
|
|
28
29
|
BOLD_OFF = "\033[22m"
|
|
29
30
|
ITALIC_OFF = "\033[23m"
|
|
30
31
|
FG_DEFAULT = "\033[39m"
|
|
32
|
+
LINK_END = "\033]8;;\033\\"
|
|
31
33
|
|
|
32
34
|
_CODEX_SYNTHETIC_PREFIXES = (
|
|
33
35
|
"<environment_context>",
|
|
@@ -235,13 +237,16 @@ _MD_INLINE_RE = re.compile(
|
|
|
235
237
|
r"|\*\*(?=\S)(.+?)(?<=\S)\*\*"
|
|
236
238
|
r"|__(?=\S)(.+?)(?<=\S)__"
|
|
237
239
|
r"|(?<![\w*])\*(?=[^\s*])(.+?)(?<=[^\s*])\*(?![\w*])"
|
|
240
|
+
r"|\[([^\]\n]+)\]\(([^)\s]+)\)"
|
|
238
241
|
)
|
|
239
242
|
_MD_TABLE_SEPARATOR_RE = re.compile(
|
|
240
243
|
r"^\s*\|?\s*:?-{3,}:?\s*(\|\s*:?-{3,}:?\s*)*\|?\s*$")
|
|
241
244
|
_MD_TABLE_CELL_SPLIT_RE = re.compile(r"(?<!\\)\|")
|
|
242
245
|
_LIST_HANG_RE = re.compile(r" *(?:(?:[-*+]|\d+[.)]) +)?")
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
# Zero-width escapes Railmux emits itself: SGR styles and OSC 8 links.
|
|
247
|
+
_ESCAPE_RE = re.compile(r"\x1b\[[0-9;]*m|\x1b\]8;;[^\x1b]*\x1b\\")
|
|
248
|
+
_WRAP_TOKEN_RE = re.compile(
|
|
249
|
+
r"\x1b\[[0-9;]*m|\x1b\]8;;[^\x1b]*\x1b\\| +|[^ \x1b]+")
|
|
245
250
|
_TASK_SUMMARY_RE = re.compile(r"<summary>(.*?)</summary>", re.DOTALL)
|
|
246
251
|
|
|
247
252
|
_char_width_function = None
|
|
@@ -267,7 +272,7 @@ def _visible_width(text: str) -> int:
|
|
|
267
272
|
# Claude pads an emoji-presentation selector (as in "⚠️") to two cells.
|
|
268
273
|
return sum(
|
|
269
274
|
1 if char == "\ufe0f" else _char_width(char)
|
|
270
|
-
for char in
|
|
275
|
+
for char in _ESCAPE_RE.sub("", text)
|
|
271
276
|
)
|
|
272
277
|
|
|
273
278
|
|
|
@@ -305,12 +310,16 @@ def _wrap_styled(line: str, width: int, hang: int) -> list[str]:
|
|
|
305
310
|
else:
|
|
306
311
|
newline()
|
|
307
312
|
continue
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
313
|
+
capacity = width - hang
|
|
314
|
+
if column + token_width > width and column > hang:
|
|
315
|
+
# Like wrap-ansi: start a word on a fresh row when that fits it,
|
|
316
|
+
# or when splitting it from there needs fewer breaks.
|
|
317
|
+
breaks_here = 1 + (token_width - (width - column) - 1) // capacity
|
|
318
|
+
if (
|
|
319
|
+
token_width <= capacity
|
|
320
|
+
or (token_width - 1) // capacity < breaks_here
|
|
321
|
+
):
|
|
322
|
+
newline()
|
|
314
323
|
for char in token:
|
|
315
324
|
char_width = _char_width(char)
|
|
316
325
|
if column + char_width > width and column > hang:
|
|
@@ -323,29 +332,49 @@ def _wrap_styled(line: str, width: int, hang: int) -> list[str]:
|
|
|
323
332
|
|
|
324
333
|
def _hang_for(row: str, prefix: int) -> int:
|
|
325
334
|
"""Hanging indent for a row whose own content starts after *prefix* cells."""
|
|
326
|
-
content =
|
|
335
|
+
content = _ESCAPE_RE.sub("", row)[prefix:]
|
|
327
336
|
return prefix + len(_LIST_HANG_RE.match(content).group(0))
|
|
328
337
|
|
|
329
338
|
|
|
330
339
|
def _close_fragments(fragments: list[str]) -> list[str]:
|
|
331
|
-
"""Make each wrapped fragment carry and close its own SGR state.
|
|
340
|
+
"""Make each wrapped fragment carry and close its own SGR and link state.
|
|
332
341
|
|
|
333
|
-
Table cells sit beside other cells on one row, so a style that
|
|
334
|
-
onto a cell's next fragment must not leak across the borders
|
|
342
|
+
Table cells sit beside other cells on one row, so a style or link that
|
|
343
|
+
continues onto a cell's next fragment must not leak across the borders.
|
|
335
344
|
"""
|
|
336
345
|
closed: list[str] = []
|
|
337
346
|
active: list[str] = []
|
|
347
|
+
link = ""
|
|
338
348
|
for fragment in fragments:
|
|
339
|
-
prefix = "".join(active)
|
|
340
|
-
for code in
|
|
341
|
-
if code
|
|
349
|
+
prefix = "".join(active) + link
|
|
350
|
+
for code in _ESCAPE_RE.findall(fragment):
|
|
351
|
+
if code.startswith("\x1b]"):
|
|
352
|
+
link = "" if code == LINK_END else code
|
|
353
|
+
elif code == RESET:
|
|
342
354
|
active.clear()
|
|
343
355
|
else:
|
|
344
356
|
active.append(code)
|
|
345
|
-
|
|
357
|
+
suffix = LINK_END if link else ""
|
|
358
|
+
closed.append(f"{prefix}{fragment}{suffix}{RESET}")
|
|
346
359
|
return closed
|
|
347
360
|
|
|
348
361
|
|
|
362
|
+
def _link(text: str, url: str) -> str:
|
|
363
|
+
"""Wrap *text* in an OSC 8 link when *url* is a plain HTTP(S) target."""
|
|
364
|
+
try:
|
|
365
|
+
parsed = urlsplit(url)
|
|
366
|
+
valid = (
|
|
367
|
+
parsed.scheme.lower() in ("http", "https")
|
|
368
|
+
and parsed.hostname is not None
|
|
369
|
+
and len(url) <= 8192
|
|
370
|
+
)
|
|
371
|
+
except ValueError:
|
|
372
|
+
valid = False
|
|
373
|
+
if not valid:
|
|
374
|
+
return text
|
|
375
|
+
return f"\033]8;;{url}\033\\{text}{LINK_END}"
|
|
376
|
+
|
|
377
|
+
|
|
349
378
|
def _table_cells(line: str) -> list[str]:
|
|
350
379
|
stripped = line.strip()
|
|
351
380
|
if stripped.startswith("|"):
|
|
@@ -373,15 +402,34 @@ def _markdown_table(lines: list[str], width: int) -> list[str] | None:
|
|
|
373
402
|
for line in lines[2:]:
|
|
374
403
|
cells = [_markdown_inline(cell) for cell in _table_cells(line)]
|
|
375
404
|
body.append((cells + [""] * count)[:count])
|
|
376
|
-
|
|
405
|
+
# Claude keeps two spare cells beside the borders and padding.
|
|
406
|
+
available = width - 3 - 3 * count
|
|
377
407
|
if available < 3 * count:
|
|
378
408
|
return None
|
|
409
|
+
rows = [header, *body]
|
|
379
410
|
natural = [
|
|
380
|
-
max(1, *(_visible_width(row[index]) for row in
|
|
411
|
+
max(1, *(_visible_width(row[index]) for row in rows))
|
|
412
|
+
for index in range(count)
|
|
413
|
+
]
|
|
414
|
+
longest_word = [
|
|
415
|
+
max(
|
|
416
|
+
_visible_width(word)
|
|
417
|
+
for row in rows
|
|
418
|
+
for word in [*_ESCAPE_RE.sub("", row[index]).split(" "), ""]
|
|
419
|
+
)
|
|
381
420
|
for index in range(count)
|
|
382
421
|
]
|
|
422
|
+
minimum = [max(1, min(a, b)) for a, b in zip(natural, longest_word)]
|
|
383
423
|
widths = natural
|
|
384
|
-
if sum(natural) > available:
|
|
424
|
+
if sum(natural) > available and sum(minimum) <= available:
|
|
425
|
+
# Claude's split: every column fits its longest word, and the spare
|
|
426
|
+
# cells go to each column in proportion to how much more it wants.
|
|
427
|
+
spare = available - sum(minimum)
|
|
428
|
+
wanted = sum(n - m for n, m in zip(natural, minimum))
|
|
429
|
+
widths = [
|
|
430
|
+
m + spare * (n - m) // wanted for n, m in zip(natural, minimum)
|
|
431
|
+
]
|
|
432
|
+
elif sum(natural) > available:
|
|
385
433
|
low, high = 3, max(natural)
|
|
386
434
|
while low < high:
|
|
387
435
|
cap = (low + high + 1) // 2
|
|
@@ -419,11 +467,12 @@ def _markdown_table(lines: list[str], width: int) -> list[str] | None:
|
|
|
419
467
|
|
|
420
468
|
|
|
421
469
|
def _markdown_inline(line: str, *, bold: bool = False) -> str:
|
|
422
|
-
"""Style inline code, bold and
|
|
470
|
+
"""Style inline code, bold, italic and link spans like Claude's view.
|
|
423
471
|
|
|
424
472
|
Only targeted "off" codes close each span, so an enclosing style (for
|
|
425
473
|
example a bold heading) survives an inner code or italic span. *bold*
|
|
426
474
|
marks an already-bold context whose nested strong spans must not end it.
|
|
475
|
+
A link shows only its text and stays clickable through OSC 8.
|
|
427
476
|
"""
|
|
428
477
|
|
|
429
478
|
def replace(match: re.Match[str]) -> str:
|
|
@@ -431,6 +480,9 @@ def _markdown_inline(line: str, *, bold: bool = False) -> str:
|
|
|
431
480
|
match.group(2), match.group(3), match.group(4), match.group(5))
|
|
432
481
|
if code is not None:
|
|
433
482
|
return f"{CLAUDE_ACCENT}{code}{FG_DEFAULT}"
|
|
483
|
+
if match.group(6) is not None:
|
|
484
|
+
return _link(_markdown_inline(match.group(6), bold=bold),
|
|
485
|
+
match.group(7))
|
|
434
486
|
if strong is not None or strong_alt is not None:
|
|
435
487
|
inner = _markdown_inline(
|
|
436
488
|
strong if strong is not None else strong_alt, bold=True)
|
|
@@ -477,6 +529,9 @@ def _markdown_lines(lines: list[str], width: int | None = None) -> list[str]:
|
|
|
477
529
|
if heading:
|
|
478
530
|
inner = _markdown_inline(heading.group(2), bold=True)
|
|
479
531
|
rendered.append(f"{BOLD}{inner}{RESET}")
|
|
532
|
+
# Claude always leaves a blank line below a heading.
|
|
533
|
+
if index < len(lines) and lines[index].strip():
|
|
534
|
+
rendered.append("")
|
|
480
535
|
continue
|
|
481
536
|
styled = _markdown_inline(line)
|
|
482
537
|
rendered.append(styled + RESET if styled != line else line)
|
|
@@ -2357,3 +2357,19 @@ def test_server_projects_only_allowlisted_private_terminal_modes():
|
|
|
2357
2357
|
mode = {1000 << 5, 1006 << 5, 9999 << 5}
|
|
2358
2358
|
|
|
2359
2359
|
assert terminal_modes_for_screen(OtherModes()) is TerminalMode.NONE
|
|
2360
|
+
|
|
2361
|
+
|
|
2362
|
+
def test_transcript_rows_reopen_links_across_wraps_and_drop_unsafe_targets():
|
|
2363
|
+
pyte = fast_display_server._extended_pyte(__import__("pyte"))
|
|
2364
|
+
link = "\x1b]8;;https://example.com/a\x1b\\"
|
|
2365
|
+
close = "\x1b]8;;\x1b\\"
|
|
2366
|
+
text = f"{link}abcdef{close} \x1b]8;;file:///etc/passwd\x1b\\x{close}\n"
|
|
2367
|
+
|
|
2368
|
+
rows, _dropped, _total = fast_display_server._wrap_transcript_rows(
|
|
2369
|
+
pyte, text, 4)
|
|
2370
|
+
|
|
2371
|
+
encoded_link, encoded_close = link.encode(), close.encode()
|
|
2372
|
+
assert rows[0] == b"\x1b[0m" + encoded_link + b"abcd" + encoded_close + b"\x1b[0m"
|
|
2373
|
+
assert rows[1].startswith(b"\x1b[0m" + encoded_link + b"ef" + encoded_close)
|
|
2374
|
+
assert b"file:" not in b"".join(rows)
|
|
2375
|
+
assert fast_display_server._overlap_text(rows[0]) == "abcd"
|
|
@@ -905,7 +905,9 @@ def _native(records, width=None):
|
|
|
905
905
|
|
|
906
906
|
|
|
907
907
|
def _plain_rows(rendered: str) -> list[str]:
|
|
908
|
-
return re.sub(
|
|
908
|
+
return re.sub(
|
|
909
|
+
r"\x1b\[[0-9;]*m|\x1b\]8;;[^\x1b]*\x1b\\", "", rendered
|
|
910
|
+
).split("\n")
|
|
909
911
|
|
|
910
912
|
|
|
911
913
|
def _assistant(text: str) -> dict:
|
|
@@ -962,12 +964,55 @@ def test_claude_native_history_draws_tables_that_fit_the_pane():
|
|
|
962
964
|
rows = _plain_rows(_native([_assistant(table)], width=30))[1:-1]
|
|
963
965
|
|
|
964
966
|
assert rows == [
|
|
965
|
-
"●
|
|
966
|
-
" │ Name │ Notes
|
|
967
|
-
"
|
|
968
|
-
" │ a │ one two three
|
|
969
|
-
" │ │ four
|
|
970
|
-
"
|
|
967
|
+
"● ┌──────┬─────────────────┐",
|
|
968
|
+
" │ Name │ Notes │",
|
|
969
|
+
" ├──────┼─────────────────┤",
|
|
970
|
+
" │ a │ one two three │",
|
|
971
|
+
" │ │ four │",
|
|
972
|
+
" └──────┴─────────────────┘",
|
|
971
973
|
]
|
|
972
974
|
assert all(len(row) <= 30 for row in rows)
|
|
973
975
|
assert table.splitlines()[0] in _native([_assistant(table)])
|
|
976
|
+
|
|
977
|
+
|
|
978
|
+
def test_claude_native_history_matches_claude_table_and_link_layout():
|
|
979
|
+
table = "\n".join([
|
|
980
|
+
"### Title",
|
|
981
|
+
"| PR | Notes |",
|
|
982
|
+
"|---|---|",
|
|
983
|
+
"| [#1](https://example.com/pull/1) | "
|
|
984
|
+
+ "alpha beta gamma delta epsilon zeta eta theta |",
|
|
985
|
+
])
|
|
986
|
+
rows = _plain_rows(_native([_assistant(table)], width=40))[1:-1]
|
|
987
|
+
|
|
988
|
+
assert rows == [
|
|
989
|
+
"● Title",
|
|
990
|
+
" ",
|
|
991
|
+
" ┌────┬─────────────────────────────┐",
|
|
992
|
+
" │ PR │ Notes │",
|
|
993
|
+
" ├────┼─────────────────────────────┤",
|
|
994
|
+
" │ #1 │ alpha beta gamma delta │",
|
|
995
|
+
" │ │ epsilon zeta eta theta │",
|
|
996
|
+
" └────┴─────────────────────────────┘",
|
|
997
|
+
]
|
|
998
|
+
|
|
999
|
+
|
|
1000
|
+
def test_claude_native_wrap_moves_long_word_when_that_saves_a_break():
|
|
1001
|
+
moved = _native([_assistant("intro " + "x" * 36)], width=20)
|
|
1002
|
+
kept = _native([_assistant("intro " + "x" * 30)], width=20)
|
|
1003
|
+
|
|
1004
|
+
assert _plain_rows(moved)[1:-1] == [
|
|
1005
|
+
"● intro", " " + "x" * 18, " " + "x" * 18,
|
|
1006
|
+
]
|
|
1007
|
+
assert _plain_rows(kept)[1:-1] == [
|
|
1008
|
+
"● intro " + "x" * 12, " " + "x" * 18,
|
|
1009
|
+
]
|
|
1010
|
+
|
|
1011
|
+
|
|
1012
|
+
def test_claude_native_links_stay_clickable_and_reject_other_schemes():
|
|
1013
|
+
rendered = _native([_assistant(
|
|
1014
|
+
"See [#1](https://example.com/pull/1) and [x](javascript:alert).")])
|
|
1015
|
+
|
|
1016
|
+
assert "\x1b]8;;https://example.com/pull/1\x1b\\#1\x1b]8;;\x1b\\" in rendered
|
|
1017
|
+
assert "javascript" not in rendered
|
|
1018
|
+
assert "See #1 and x." in "\n".join(_plain_rows(rendered))
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.4.2.dev6"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|