par-term-emu-core-rust 0.28.0__tar.gz → 0.30.0__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.
Files changed (139) hide show
  1. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/CHANGELOG.md +36 -0
  2. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/Cargo.lock +3 -1
  3. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/Cargo.toml +3 -1
  4. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/PKG-INFO +69 -1
  5. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/README.md +68 -0
  6. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/ADVANCED_FEATURES.md +36 -0
  7. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/API_REFERENCE.md +26 -3
  8. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/CONFIG_REFERENCE.md +5 -3
  9. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/VT_SEQUENCES.md +1 -1
  10. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/VT_TECHNICAL_REFERENCE.md +2 -2
  11. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/pyproject.toml +1 -1
  12. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/python/par_term_emu_core_rust/__init__.py +1 -1
  13. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/pty.rs +33 -0
  14. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/terminal.rs +217 -2
  15. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/types.rs +10 -1
  16. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/shell_integration.rs +76 -0
  17. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/colors.rs +24 -0
  18. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/mod.rs +164 -6
  19. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/csi.rs +57 -0
  20. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/osc.rs +240 -21
  21. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/uv.lock +1 -1
  22. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/.claude/agents/rust-python-terminal-expert.md +0 -0
  23. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/AGENTS.md +0 -0
  24. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/LICENSE +0 -0
  25. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/QUICKSTART.md +0 -0
  26. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/build.rs +0 -0
  27. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/debug/diagnose_corruption.py +0 -0
  28. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/debug/test_debug_features.py +0 -0
  29. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/debug/test_wide_chars.py +0 -0
  30. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/ARCHITECTURE.md +0 -0
  31. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/BUILDING.md +0 -0
  32. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/CROSS_PLATFORM.md +0 -0
  33. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/DOCUMENTATION_STYLE_GUIDE.md +0 -0
  34. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/FONTS.md +0 -0
  35. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/GRAPHICS_TESTING.md +0 -0
  36. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/MACROS.md +0 -0
  37. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/MATURIN_BEST_PRACTICES.md +0 -0
  38. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/REGIONAL_FLAG_LIMITATION.md +0 -0
  39. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/RUST_USAGE.md +0 -0
  40. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/SECURITY.md +0 -0
  41. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/STREAMING.md +0 -0
  42. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/docs/TESTING_KITTY_ANIMATIONS.md +0 -0
  43. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/future-optimizations.md +0 -0
  44. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/proto/terminal.proto +0 -0
  45. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/pyrightconfig.json +0 -0
  46. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/python/par_term_emu_core_rust/debug.py +0 -0
  47. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/requirements-dev.txt +0 -0
  48. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/ansi_utils.rs +0 -0
  49. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/badge.rs +0 -0
  50. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/bin/streaming_server.rs +0 -0
  51. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/cell.rs +0 -0
  52. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/color.rs +0 -0
  53. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/color_utils.rs +0 -0
  54. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/conformance_level.rs +0 -0
  55. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/cursor.rs +0 -0
  56. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/debug.rs +0 -0
  57. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/grapheme.rs +0 -0
  58. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/graphics/animation.rs +0 -0
  59. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/graphics/iterm.rs +0 -0
  60. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/graphics/kitty.rs +0 -0
  61. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/graphics/mod.rs +0 -0
  62. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/graphics/placeholder.rs +0 -0
  63. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/grid.rs +0 -0
  64. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/html_export.rs +0 -0
  65. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/lib.rs +0 -0
  66. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/macros.rs +0 -0
  67. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/mouse.rs +0 -0
  68. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/pty_error.rs +0 -0
  69. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/pty_session.rs +0 -0
  70. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/color_utils.rs +0 -0
  71. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/conversions.rs +0 -0
  72. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/enums.rs +0 -0
  73. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/mod.rs +0 -0
  74. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/streaming.rs +0 -0
  75. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/JetBrainsMono-Regular.ttf +0 -0
  76. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/NotoEmoji-Regular.ttf +0 -0
  77. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/config.rs +0 -0
  78. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/error.rs +0 -0
  79. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/font_cache.rs +0 -0
  80. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/bmp.rs +0 -0
  81. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/jpeg.rs +0 -0
  82. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/mod.rs +0 -0
  83. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/png.rs +0 -0
  84. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/svg.rs +0 -0
  85. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/mod.rs +0 -0
  86. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/renderer.rs +0 -0
  87. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/shaper.rs +0 -0
  88. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/utils.rs +0 -0
  89. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/sixel.rs +0 -0
  90. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/broadcaster.rs +0 -0
  91. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/client.rs +0 -0
  92. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/error.rs +0 -0
  93. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/mod.rs +0 -0
  94. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/proto.rs +0 -0
  95. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/protocol.rs +0 -0
  96. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/server.rs +0 -0
  97. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/streaming/terminal.pb.rs +0 -0
  98. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/graphics.rs +0 -0
  99. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/notification.rs +0 -0
  100. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/progress.rs +0 -0
  101. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/dcs.rs +0 -0
  102. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/esc.rs +0 -0
  103. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/mod.rs +0 -0
  104. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/terminal/write.rs +0 -0
  105. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/text_utils.rs +0 -0
  106. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/tmux_control.rs +0 -0
  107. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/src/unicode_width_config.rs +0 -0
  108. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/theme.css +0 -0
  109. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/__next.__PAGE__.txt +0 -0
  110. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._full.txt +0 -0
  111. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._head.txt +0 -0
  112. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._index.txt +0 -0
  113. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._tree.txt +0 -0
  114. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/0e7e54b03353fc64.js +0 -0
  115. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/2f236954d6a65e12.js +0 -0
  116. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/6a145f7d64f5cf03.js +0 -0
  117. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/6bd3cb3b56d06ca6.js +0 -0
  118. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/808d100a753cdcf2.js +0 -0
  119. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/a27b4f205d48ece2.css +0 -0
  120. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/a6dad97d9634a72d.js +0 -0
  121. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/a6dad97d9634a72d.js.map +0 -0
  122. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/e1140cc73d7c6ca2.js +0 -0
  123. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/ed8d72bcbb9aa3b2.js +0 -0
  124. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/chunks/turbopack-b9888d6049f35c64.js +0 -0
  125. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/qD3YDPAUHYDX2LyueNPUO/_buildManifest.js +0 -0
  126. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/qD3YDPAUHYDX2LyueNPUO/_clientMiddlewareManifest.json +0 -0
  127. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_next/static/qD3YDPAUHYDX2LyueNPUO/_ssgManifest.js +0 -0
  128. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found/__next._full.txt +0 -0
  129. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found/__next._head.txt +0 -0
  130. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found/__next._index.txt +0 -0
  131. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found/__next._not-found.__PAGE__.txt +0 -0
  132. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found/__next._not-found.txt +0 -0
  133. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found/__next._tree.txt +0 -0
  134. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found.txt +0 -0
  135. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/favicon.ico +0 -0
  136. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/index.txt +0 -0
  137. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/manifest.json +0 -0
  138. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/web_term/theme.css +0 -0
  139. {par_term_emu_core_rust-0.28.0 → par_term_emu_core_rust-0.30.0}/xterm-issue-draft.md +0 -0
@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ## [0.30.0] - 2026-02-04
11
+
12
+ ### Added
13
+ - **modifyOtherKeys Protocol**: XTerm extension for enhanced keyboard input reporting
14
+ - State tracking for modifyOtherKeys mode (0=disabled, 1=special keys, 2=all keys)
15
+ - CSI sequence parsing: `CSI > 4 ; mode m` to set mode
16
+ - Query support: `CSI ? 4 m` returns `CSI > 4 ; mode m` response
17
+ - New methods: `modify_other_keys_mode()` getter, `set_modify_other_keys_mode()` setter
18
+ - Mode resets on terminal reset and alternate screen exit
19
+ - 9 new tests for modifyOtherKeys functionality
20
+ - **Faint Text Alpha**: Configurable alpha multiplier for SGR 2 (dim/faint) text
21
+ - New `faint_text_alpha` field in Terminal (default: 0.5 for 50% dimming)
22
+ - New methods: `faint_text_alpha()` getter, `set_faint_text_alpha(alpha)` setter
23
+ - Values clamped to 0.0-1.0 range
24
+ - Propagated to screenshot renderer for consistent rendering
25
+ - Python bindings for both Terminal and PtyTerminal classes
26
+
27
+ ## [0.29.0] - 2026-02-04
28
+
29
+ ### Added
30
+ - **OSC 7 Enhancements**: Percent-decoding, username/hostname parsing, port stripping, query/fragment removal, and path validation for `file://` URLs
31
+ - **Session Variable Sync**: OSC 7 now updates badge/session variables (`path`, `hostname`, `username`) so badge formats immediately reflect directory changes
32
+ - **CWD History Context**: CWD change log now records hostname and username; Python `CwdChange` exposes these fields
33
+ - **CWD Change Events**: New `TerminalEvent::CwdChanged` (and Python `cwd_changed` poll_events entry) fires on OSC 7 or manual `record_cwd_change`
34
+ - **Username Handling**: Shell integration stores optional username from `user@host` OSC 7 payloads
35
+
36
+ ### Changed
37
+ - **API**: `record_cwd_change` now accepts optional `hostname` and `username` (defaults preserved); badge/session variables cleared when hostname/username unset
38
+ - **Dependencies**: Added `percent-encoding` and `url` crates for robust OSC 7 parsing
39
+
40
+ ### Fixed
41
+ - **Badge Accuracy**: Badge variables `\(path)` and `\(hostname)` now stay in sync when updated via OSC 7
42
+ - **UTF-8 Paths**: Paths with spaces or Unicode characters from OSC 7 are correctly percent-decoded
43
+
8
44
  ## [0.28.0] - 2026-02-03
9
45
 
10
46
  ### Added
@@ -1767,7 +1767,7 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
1767
1767
 
1768
1768
  [[package]]
1769
1769
  name = "par-term-emu-core-rust"
1770
- version = "0.28.0"
1770
+ version = "0.30.0"
1771
1771
  dependencies = [
1772
1772
  "anyhow",
1773
1773
  "axum",
@@ -1782,6 +1782,7 @@ dependencies = [
1782
1782
  "image",
1783
1783
  "libc",
1784
1784
  "parking_lot",
1785
+ "percent-encoding",
1785
1786
  "portable-pty",
1786
1787
  "proptest",
1787
1788
  "prost",
@@ -1806,6 +1807,7 @@ dependencies = [
1806
1807
  "tracing-subscriber",
1807
1808
  "unicode-segmentation",
1808
1809
  "unicode-width",
1810
+ "url",
1809
1811
  "uuid",
1810
1812
  "vte",
1811
1813
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "par-term-emu-core-rust"
3
- version = "0.28.0"
3
+ version = "0.30.0"
4
4
  edition = "2021"
5
5
  rust-version = "1.75"
6
6
  authors = ["Paul Robello <probello@gmail.com>"]
@@ -57,6 +57,8 @@ regex = "1.12.2"
57
57
  serde = { version = "1.0.228", features = ["derive"] }
58
58
  serde_json = "1.0.149"
59
59
  serde_yaml = "0.9.34"
60
+ percent-encoding = "2.3.2"
61
+ url = "2.5.8"
60
62
 
61
63
  # Streaming server dependencies
62
64
  tokio = { version = "1.49", features = ["full"], optional = true }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: par-term-emu-core-rust
3
- Version: 0.28.0
3
+ Version: 0.30.0
4
4
  Classifier: License :: OSI Approved :: MIT License
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Development Status :: 4 - Beta
@@ -50,6 +50,73 @@ A comprehensive terminal emulator library written in Rust with Python bindings f
50
50
 
51
51
  [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://buymeacoffee.com/probello3)
52
52
 
53
+ ## What's New in 0.30.0
54
+
55
+ ### ⌨️ modifyOtherKeys Protocol Support
56
+
57
+ XTerm extension for enhanced keyboard input reporting, enabling applications to receive modifier keys with regular characters:
58
+
59
+ ```python
60
+ from par_term_emu_core_rust import Terminal
61
+
62
+ term = Terminal(80, 24)
63
+
64
+ # Enable modifyOtherKeys mode via escape sequence
65
+ term.process(b"\x1b[>4;2m") # Mode 2: report all keys with modifiers
66
+ print(f"Mode: {term.modify_other_keys_mode()}") # Output: 2
67
+
68
+ # Or set directly
69
+ term.set_modify_other_keys_mode(1) # Mode 1: special keys only
70
+
71
+ # Query mode (response in drain_responses())
72
+ term.process(b"\x1b[?4m")
73
+ response = term.drain_responses() # Returns b"\x1b[>4;1m"
74
+ ```
75
+
76
+ **Modes:**
77
+ - `0` - Disabled (default)
78
+ - `1` - Report modifiers for special keys only
79
+ - `2` - Report modifiers for all keys
80
+
81
+ **New Methods:**
82
+ - `modify_other_keys_mode()` - Get current mode
83
+ - `set_modify_other_keys_mode(mode)` - Set mode directly (values > 2 clamped to 2)
84
+
85
+ **Sequences:**
86
+ - `CSI > 4 ; mode m` - Set mode
87
+ - `CSI ? 4 m` - Query mode (response: `CSI > 4 ; mode m`)
88
+
89
+ **Note:** Mode resets to 0 on terminal reset and when exiting alternate screen.
90
+
91
+ ### 🎨 Faint Text Alpha Control
92
+
93
+ Configurable alpha multiplier for SGR 2 (dim/faint) text, allowing fine-grained control over how dim text is rendered:
94
+
95
+ ```python
96
+ from par_term_emu_core_rust import Terminal
97
+
98
+ term = Terminal(80, 24)
99
+
100
+ # Get current faint text alpha (default: 0.5 = 50% dimming)
101
+ print(f"Alpha: {term.faint_text_alpha()}") # Output: 0.5
102
+
103
+ # Set faint text to be more transparent (more dimmed)
104
+ term.set_faint_text_alpha(0.3) # 30% opacity
105
+
106
+ # Set faint text to be less transparent (less dimmed)
107
+ term.set_faint_text_alpha(0.7) # 70% opacity
108
+
109
+ # Values are clamped to 0.0-1.0 range
110
+ term.set_faint_text_alpha(1.5) # Clamped to 1.0
111
+ term.set_faint_text_alpha(-0.5) # Clamped to 0.0
112
+ ```
113
+
114
+ **New Methods:**
115
+ - `faint_text_alpha()` - Get current alpha multiplier (0.0-1.0)
116
+ - `set_faint_text_alpha(alpha)` - Set alpha multiplier (clamped to valid range)
117
+
118
+ **Usage:** This setting is used by the screenshot renderer and can be queried by frontends for consistent rendering of dim text (SGR 2).
119
+
53
120
  ## What's New in 0.28.0
54
121
 
55
122
  ### 🏷️ Badge Format Support (OSC 1337 SetBadgeFormat)
@@ -576,6 +643,7 @@ make streamer-build-release
576
643
  - Mouse encoding control: `mouse_encoding()`, `set_mouse_encoding()`
577
644
  - Mode setters: `set_focus_tracking()`, `set_bracketed_paste()`, `set_title()`
578
645
  - Bold brightening control: `bold_brightening()`, `set_bold_brightening()`
646
+ - Faint text alpha control: `faint_text_alpha()`, `set_faint_text_alpha()`
579
647
  - Color getters for all theme colors (link, bold, cursor guide, badge, match, selection)
580
648
 
581
649
  ## What's New in 0.12.0
@@ -13,6 +13,73 @@ A comprehensive terminal emulator library written in Rust with Python bindings f
13
13
 
14
14
  [!["Buy Me A Coffee"](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://buymeacoffee.com/probello3)
15
15
 
16
+ ## What's New in 0.30.0
17
+
18
+ ### ⌨️ modifyOtherKeys Protocol Support
19
+
20
+ XTerm extension for enhanced keyboard input reporting, enabling applications to receive modifier keys with regular characters:
21
+
22
+ ```python
23
+ from par_term_emu_core_rust import Terminal
24
+
25
+ term = Terminal(80, 24)
26
+
27
+ # Enable modifyOtherKeys mode via escape sequence
28
+ term.process(b"\x1b[>4;2m") # Mode 2: report all keys with modifiers
29
+ print(f"Mode: {term.modify_other_keys_mode()}") # Output: 2
30
+
31
+ # Or set directly
32
+ term.set_modify_other_keys_mode(1) # Mode 1: special keys only
33
+
34
+ # Query mode (response in drain_responses())
35
+ term.process(b"\x1b[?4m")
36
+ response = term.drain_responses() # Returns b"\x1b[>4;1m"
37
+ ```
38
+
39
+ **Modes:**
40
+ - `0` - Disabled (default)
41
+ - `1` - Report modifiers for special keys only
42
+ - `2` - Report modifiers for all keys
43
+
44
+ **New Methods:**
45
+ - `modify_other_keys_mode()` - Get current mode
46
+ - `set_modify_other_keys_mode(mode)` - Set mode directly (values > 2 clamped to 2)
47
+
48
+ **Sequences:**
49
+ - `CSI > 4 ; mode m` - Set mode
50
+ - `CSI ? 4 m` - Query mode (response: `CSI > 4 ; mode m`)
51
+
52
+ **Note:** Mode resets to 0 on terminal reset and when exiting alternate screen.
53
+
54
+ ### 🎨 Faint Text Alpha Control
55
+
56
+ Configurable alpha multiplier for SGR 2 (dim/faint) text, allowing fine-grained control over how dim text is rendered:
57
+
58
+ ```python
59
+ from par_term_emu_core_rust import Terminal
60
+
61
+ term = Terminal(80, 24)
62
+
63
+ # Get current faint text alpha (default: 0.5 = 50% dimming)
64
+ print(f"Alpha: {term.faint_text_alpha()}") # Output: 0.5
65
+
66
+ # Set faint text to be more transparent (more dimmed)
67
+ term.set_faint_text_alpha(0.3) # 30% opacity
68
+
69
+ # Set faint text to be less transparent (less dimmed)
70
+ term.set_faint_text_alpha(0.7) # 70% opacity
71
+
72
+ # Values are clamped to 0.0-1.0 range
73
+ term.set_faint_text_alpha(1.5) # Clamped to 1.0
74
+ term.set_faint_text_alpha(-0.5) # Clamped to 0.0
75
+ ```
76
+
77
+ **New Methods:**
78
+ - `faint_text_alpha()` - Get current alpha multiplier (0.0-1.0)
79
+ - `set_faint_text_alpha(alpha)` - Set alpha multiplier (clamped to valid range)
80
+
81
+ **Usage:** This setting is used by the screenshot renderer and can be queried by frontends for consistent rendering of dim text (SGR 2).
82
+
16
83
  ## What's New in 0.28.0
17
84
 
18
85
  ### 🏷️ Badge Format Support (OSC 1337 SetBadgeFormat)
@@ -539,6 +606,7 @@ make streamer-build-release
539
606
  - Mouse encoding control: `mouse_encoding()`, `set_mouse_encoding()`
540
607
  - Mode setters: `set_focus_tracking()`, `set_bracketed_paste()`, `set_title()`
541
608
  - Bold brightening control: `bold_brightening()`, `set_bold_brightening()`
609
+ - Faint text alpha control: `faint_text_alpha()`, `set_faint_text_alpha()`
542
610
  - Color getters for all theme colors (link, bold, cursor guide, badge, match, selection)
543
611
 
544
612
  ## What's New in 0.12.0
@@ -155,6 +155,42 @@ term.process_str("\x1b[1;31mThis appears regular red (bold)\x1b[0m\n")
155
155
 
156
156
  **Note**: Bold brightening only affects ANSI colors 0-7, not 256-color or RGB colors. When creating snapshots with `create_snapshot()` or taking screenshots with `screenshot()` / `screenshot_to_file()`, the bold brightening setting is automatically applied to the captured colors.
157
157
 
158
+ ## Faint/Dim Text Alpha (SGR 2)
159
+
160
+ The faint text alpha controls how dim SGR 2 (faint/dim) text appears. This is the alpha multiplier applied to dim text during rendering.
161
+
162
+ ### Overview
163
+
164
+ - **Range**: 0.0-1.0 where 0.0 = fully transparent, 1.0 = fully opaque
165
+ - **Default**: 0.5 (50% opacity - text is blended with background)
166
+ - **SGR Code**: Applied when text has the SGR 2 (dim/faint) attribute
167
+
168
+ ### Usage
169
+
170
+ ```python
171
+ from par_term_emu_core_rust import Terminal
172
+
173
+ term = Terminal(80, 24)
174
+
175
+ # Check current faint text alpha (default 0.5)
176
+ print(f"Alpha: {term.faint_text_alpha()}") # Output: 0.5
177
+
178
+ # Make dim text more transparent (more dimmed)
179
+ term.set_faint_text_alpha(0.3)
180
+
181
+ # Process text with dim attribute (SGR 2)
182
+ term.process_str("\x1b[2mThis text is dimmed\x1b[0m\n")
183
+
184
+ # Make dim text less transparent (less dimmed)
185
+ term.set_faint_text_alpha(0.7)
186
+
187
+ # Values are clamped to 0.0-1.0 range
188
+ term.set_faint_text_alpha(1.5) # Becomes 1.0
189
+ term.set_faint_text_alpha(-0.5) # Becomes 0.0
190
+ ```
191
+
192
+ **Note**: The faint text alpha is automatically applied when taking screenshots with `screenshot()` / `screenshot_to_file()`. Frontends can query this value via `faint_text_alpha()` to apply consistent dimming during real-time rendering.
193
+
158
194
  ## Minimum Contrast Adjustment (iTerm2-Compatible)
159
195
 
160
196
  The minimum contrast feature automatically adjusts text colors to ensure readability against backgrounds, using the same algorithm as iTerm2.
@@ -177,6 +177,16 @@ badge = term.evaluate_badge() # "alice@server1"
177
177
 
178
178
  **Note:** Flags are maintained separately for main and alternate screen buffers with independent stacks. Automatically reset when exiting alternate screen.
179
179
 
180
+ #### modifyOtherKeys (XTerm Extension)
181
+ - `modify_other_keys_mode() -> int`: Get current mode (0=disabled, 1=special keys, 2=all keys)
182
+ - `set_modify_other_keys_mode(mode: int)`: Set mode directly (values > 2 clamped to 2)
183
+
184
+ **Sequences:**
185
+ - `CSI > 4 ; mode m` - Set mode via escape sequence
186
+ - `CSI ? 4 m` - Query mode (response: `CSI > 4 ; mode m` in drain_responses())
187
+
188
+ **Note:** Mode resets to 0 on terminal reset and when exiting alternate screen.
189
+
180
190
  #### Clipboard Operations (OSC 52)
181
191
  - `clipboard() -> str | None`: Get clipboard content
182
192
  - `set_clipboard(content: str | None)`: Set clipboard content programmatically
@@ -275,12 +285,15 @@ badge = term.evaluate_badge() # "alice@server1"
275
285
  - `set_use_underline_color(use_underline: bool)`: Enable/disable custom underline color
276
286
  - `bold_brightening() -> bool`: Check if bold text with colors 0-7 is brightened to 8-15
277
287
  - `set_bold_brightening(enabled: bool)`: Enable/disable bold brightening (legacy behavior)
288
+ - `faint_text_alpha() -> float`: Get alpha multiplier for SGR 2 (dim/faint) text (0.0-1.0, default 0.5)
289
+ - `set_faint_text_alpha(alpha: float)`: Set alpha multiplier for dim text (clamped to 0.0-1.0)
278
290
 
279
291
  #### Shell Integration (OSC 133 & OSC 7)
280
292
  - `current_directory() -> str | None`: Get current working directory (OSC 7)
281
293
  - `accept_osc7() -> bool`: Check if OSC 7 (CWD) is accepted
282
294
  - `set_accept_osc7(accept: bool)`: Set whether to accept OSC 7 sequences
283
295
  - `shell_integration_state() -> ShellIntegration`: Get shell integration state
296
+ - `record_cwd_change(new_cwd: str, hostname: str | None = None, username: str | None = None)`: Manually record a CWD change (updates history + session variables)
284
297
  - `disable_insecure_sequences() -> bool`: Check if insecure sequences are disabled
285
298
  - `set_disable_insecure_sequences(disable: bool)`: Disable insecure/dangerous sequences
286
299
  - `answerback_string() -> str | None`: Get the configured ENQ answerback payload (None if disabled)
@@ -409,10 +422,11 @@ Extended shell integration features beyond basic OSC 133:
409
422
  - `end_command_execution(exit_code: int)`: Mark end of command with exit code
410
423
  - `get_current_command() -> CommandExecution | None`: Get currently executing command
411
424
  - `get_shell_integration_stats() -> ShellIntegrationStats`: Get shell integration statistics
412
- - `get_cwd_changes() -> list[CwdChange]`: Get working directory change history
425
+ - `get_cwd_changes() -> list[CwdChange]`: Get working directory change history (includes hostname/username)
413
426
  - `clear_cwd_history()`: Clear CWD history
414
427
  - `set_max_cwd_history(max: int)`: Set CWD history limit
415
- - `record_cwd_change(cwd: str)`: Record working directory change
428
+ - `record_cwd_change(cwd: str, hostname: str | None = None, username: str | None = None)`: Record working directory change
429
+ - `poll_events()`: Now also returns `cwd_changed` events with `old_cwd`, `new_cwd`, `hostname`, `username`, `timestamp`
416
430
 
417
431
  ### Clipboard Extended
418
432
 
@@ -529,6 +543,10 @@ VT compliance testing:
529
543
  - `use_alt_screen()`: Switch to alternate screen buffer (programmatic, not via escape codes)
530
544
  - `use_primary_screen()`: Switch to primary screen buffer (programmatic)
531
545
  - `poll_events() -> list[str]`: Poll for pending terminal events
546
+ - `set_event_subscription(kinds: list[str] | None)`: Filter which terminal events are returned by `poll_subscribed_events()` (None clears filter)
547
+ - `clear_event_subscription()`: Clear event filter (all events are returned)
548
+ - `poll_subscribed_events() -> list[dict]`: Drain events that match subscription filter
549
+ - `poll_cwd_events() -> list[dict]`: Drain only CWD change events (fields: new_cwd, old_cwd?, hostname?, username?, timestamp)
532
550
  - `update_animations()`: Update animation frames (for blinking cursor, text, etc.)
533
551
  - `debug_info() -> str`: Get debug information string
534
552
  - `detect_urls(text: str) -> list[DetectedItem]`: Detect URLs in text
@@ -624,6 +642,8 @@ PtyTerminal(cols: int, rows: int, scrollback: int = 10000)
624
642
 
625
643
  #### Appearance Settings (PTY-Specific)
626
644
  - `set_bold_brightening(enabled: bool)`: Enable/disable bold brightening (ANSI colors 0-7 → 8-15)
645
+ - `faint_text_alpha() -> float`: Get alpha multiplier for SGR 2 (dim/faint) text (0.0-1.0, default 0.5)
646
+ - `set_faint_text_alpha(alpha: float)`: Set alpha multiplier for dim text (clamped to 0.0-1.0)
627
647
 
628
648
  **Note:** PtyTerminal inherits all Terminal methods, so you can also use all Terminal appearance settings like `set_default_fg()`, `set_default_bg()`, etc.
629
649
 
@@ -897,7 +917,10 @@ Working directory change event.
897
917
 
898
918
  **Properties:**
899
919
  - `cwd: str`: New working directory path
900
- - `timestamp: int`: Change timestamp (Unix timestamp in seconds)
920
+ - `old_cwd: str | None`: Previous working directory (if any)
921
+ - `hostname: str | None`: Hostname associated with the new path (None for localhost)
922
+ - `username: str | None`: Username from `user@host` portion of OSC 7 (if provided)
923
+ - `timestamp: int`: Change timestamp (Unix timestamp in milliseconds)
901
924
 
902
925
  ### DamageRegion
903
926
 
@@ -256,9 +256,11 @@ These settings control potentially sensitive or insecure terminal features at th
256
256
  - Use in untrusted/sandboxed environments
257
257
 
258
258
  **OSC 7 Directory Tracking:**
259
- - Generally safe to keep enabled
260
- - Used for shell integration and smart directory tracking
261
- - Disable if you don't need this feature
259
+ - Parses `file://[user@]host[:port]/path` URLs from shells (e.g., PROMPT_COMMAND)
260
+ - Percent-decodes paths/usernames and strips query/fragment
261
+ - Updates shell integration + badge/session variables (`\(path)`, `\(hostname)`, `\(username)`)
262
+ - Records CWD history with timestamps and host/user context
263
+ - Generally safe to keep enabled; disable if you don't need this feature
262
264
 
263
265
  ---
264
266
 
@@ -296,7 +296,7 @@ Operating System Command sequences for advanced features (format: `OSC Ps ; Pt S
296
296
  - `OSC 2;title ST` - Set window title only
297
297
  - `OSC 21;title ST` - Push title to stack (or `OSC 21 ST` to push current title)
298
298
  - `OSC 22 ST` / `OSC 23 ST` - Pop window/icon title from stack
299
- - `OSC 7;file://host/path ST` - Set current working directory (URL-encoded)
299
+ - `OSC 7;file://[user@]host[:port]/path ST` - Set current working directory (percent-decoded; strips query/fragment; `localhost` is treated as None)
300
300
 
301
301
  ### Hyperlinks and Clipboard
302
302
 
@@ -741,7 +741,7 @@ where `ST` is either `ESC \` or `BEL` (`\x07`)
741
741
 
742
742
  | Sequence | Operation | Notes |
743
743
  |----------|-----------|-------|
744
- | `OSC 7 ; file://host/cwd ST` | Set working directory | Can be disabled via `accept_osc7` |
744
+ | `OSC 7 ; file://[user@]host[:port]/cwd ST` | Set working directory | Percent-decodes path/username, strips query/fragment, ignores `localhost`, records hostname & username in session variables, can be disabled via `accept_osc7` |
745
745
 
746
746
  **Format:** `file://hostname/path` (URL-encoded path)
747
747
 
@@ -1338,7 +1338,7 @@ The terminal provides comprehensive support for complex Unicode grapheme cluster
1338
1338
  | OSC 8 Hyperlinks | ✅ Full | `src/terminal/sequences/osc.rs` | With deduplication |
1339
1339
  | OSC 52 Clipboard | ✅ Full | `src/terminal/sequences/osc.rs` | Read/write with security controls |
1340
1340
  | OSC 133 Shell Integration | ✅ Full | `src/terminal/sequences/osc.rs` | Prompt/command/output markers |
1341
- | OSC 7 Directory Tracking | ✅ Full | `src/terminal/sequences/osc.rs` | URL-encoded paths |
1341
+ | OSC 7 Directory Tracking | ✅ Full | `src/terminal/sequences/osc.rs` | Percent-decoded paths, username, hostname, session variable sync, CWD history |
1342
1342
  | OSC 9;4 Progress Bar | ✅ Full | `src/terminal/sequences/osc.rs`, `src/terminal/progress.rs` | ConEmu/Windows Terminal style progress |
1343
1343
  | Underline styles | ✅ Full | `src/terminal/sequences/csi.rs` | 6 different styles |
1344
1344
 
@@ -6,7 +6,7 @@ build-backend = "maturin"
6
6
 
7
7
  [project]
8
8
  name = "par-term-emu-core-rust"
9
- version = "0.28.0"
9
+ version = "0.30.0"
10
10
  description = "A comprehensive terminal emulator library in Rust with Python bindings - supports true color, alt screen, mouse reporting, bracketed paste, and full Unicode"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.12"
@@ -84,7 +84,7 @@ except ImportError:
84
84
  encode_client_message = None
85
85
  decode_client_message = None
86
86
 
87
- __version__ = "0.28.0"
87
+ __version__ = "0.30.0"
88
88
  __all__ = [
89
89
  "AmbiguousWidth",
90
90
  "Attributes",
@@ -1423,6 +1423,39 @@ impl PyPtyTerminal {
1423
1423
  Ok(())
1424
1424
  }
1425
1425
 
1426
+ /// Get faint/dim text alpha multiplier
1427
+ ///
1428
+ /// This value is applied to SGR 2 (dim/faint) text during rendering.
1429
+ /// A value of 0.5 means 50% opacity (the default).
1430
+ ///
1431
+ /// Returns:
1432
+ /// Alpha multiplier between 0.0 and 1.0
1433
+ fn faint_text_alpha(&self) -> PyResult<f32> {
1434
+ let terminal = self.inner.terminal();
1435
+ if let Ok(term) = Ok::<_, ()>(terminal.lock()) {
1436
+ return Ok(term.faint_text_alpha());
1437
+ }
1438
+ Ok(0.5) // Default if lock fails
1439
+ }
1440
+
1441
+ /// Set faint/dim text alpha multiplier
1442
+ ///
1443
+ /// This value is applied to SGR 2 (dim/faint) text during rendering.
1444
+ /// Values are clamped to the range 0.0-1.0.
1445
+ ///
1446
+ /// Args:
1447
+ /// alpha: Alpha multiplier (0.0 = fully transparent, 1.0 = fully opaque)
1448
+ ///
1449
+ /// Example:
1450
+ /// >>> pty.set_faint_text_alpha(0.3) # 30% opacity for dim text
1451
+ fn set_faint_text_alpha(&mut self, alpha: f32) -> PyResult<()> {
1452
+ let terminal = self.inner.terminal();
1453
+ if let Ok(mut term) = Ok::<_, ()>(terminal.lock()) {
1454
+ term.set_faint_text_alpha(alpha);
1455
+ }
1456
+ Ok(())
1457
+ }
1458
+
1426
1459
  /// Enable/disable custom underline color
1427
1460
  ///
1428
1461
  /// When enabled, underlined text uses a custom underline color.