par-term-emu-core-rust 0.29.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.29.0 → par_term_emu_core_rust-0.30.0}/CHANGELOG.md +19 -0
  2. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/Cargo.lock +1 -1
  3. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/Cargo.toml +1 -1
  4. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/PKG-INFO +69 -1
  5. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/README.md +68 -0
  6. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/ADVANCED_FEATURES.md +36 -0
  7. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/API_REFERENCE.md +14 -0
  8. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/pyproject.toml +1 -1
  9. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/python/par_term_emu_core_rust/__init__.py +1 -1
  10. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/pty.rs +33 -0
  11. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/terminal.rs +56 -0
  12. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/colors.rs +24 -0
  13. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/mod.rs +37 -0
  14. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/csi.rs +57 -0
  15. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/uv.lock +1 -1
  16. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/.claude/agents/rust-python-terminal-expert.md +0 -0
  17. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/AGENTS.md +0 -0
  18. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/LICENSE +0 -0
  19. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/QUICKSTART.md +0 -0
  20. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/build.rs +0 -0
  21. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/debug/diagnose_corruption.py +0 -0
  22. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/debug/test_debug_features.py +0 -0
  23. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/debug/test_wide_chars.py +0 -0
  24. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/ARCHITECTURE.md +0 -0
  25. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/BUILDING.md +0 -0
  26. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/CONFIG_REFERENCE.md +0 -0
  27. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/CROSS_PLATFORM.md +0 -0
  28. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/DOCUMENTATION_STYLE_GUIDE.md +0 -0
  29. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/FONTS.md +0 -0
  30. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/GRAPHICS_TESTING.md +0 -0
  31. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/MACROS.md +0 -0
  32. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/MATURIN_BEST_PRACTICES.md +0 -0
  33. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/REGIONAL_FLAG_LIMITATION.md +0 -0
  34. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/RUST_USAGE.md +0 -0
  35. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/SECURITY.md +0 -0
  36. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/STREAMING.md +0 -0
  37. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/TESTING_KITTY_ANIMATIONS.md +0 -0
  38. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/VT_SEQUENCES.md +0 -0
  39. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/docs/VT_TECHNICAL_REFERENCE.md +0 -0
  40. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/future-optimizations.md +0 -0
  41. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/proto/terminal.proto +0 -0
  42. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/pyrightconfig.json +0 -0
  43. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/python/par_term_emu_core_rust/debug.py +0 -0
  44. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/requirements-dev.txt +0 -0
  45. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/ansi_utils.rs +0 -0
  46. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/badge.rs +0 -0
  47. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/bin/streaming_server.rs +0 -0
  48. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/cell.rs +0 -0
  49. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/color.rs +0 -0
  50. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/color_utils.rs +0 -0
  51. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/conformance_level.rs +0 -0
  52. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/cursor.rs +0 -0
  53. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/debug.rs +0 -0
  54. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/grapheme.rs +0 -0
  55. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/graphics/animation.rs +0 -0
  56. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/graphics/iterm.rs +0 -0
  57. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/graphics/kitty.rs +0 -0
  58. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/graphics/mod.rs +0 -0
  59. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/graphics/placeholder.rs +0 -0
  60. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/grid.rs +0 -0
  61. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/html_export.rs +0 -0
  62. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/lib.rs +0 -0
  63. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/macros.rs +0 -0
  64. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/mouse.rs +0 -0
  65. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/pty_error.rs +0 -0
  66. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/pty_session.rs +0 -0
  67. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/color_utils.rs +0 -0
  68. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/conversions.rs +0 -0
  69. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/enums.rs +0 -0
  70. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/mod.rs +0 -0
  71. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/streaming.rs +0 -0
  72. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/python_bindings/types.rs +0 -0
  73. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/JetBrainsMono-Regular.ttf +0 -0
  74. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/NotoEmoji-Regular.ttf +0 -0
  75. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/config.rs +0 -0
  76. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/error.rs +0 -0
  77. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/font_cache.rs +0 -0
  78. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/bmp.rs +0 -0
  79. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/jpeg.rs +0 -0
  80. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/mod.rs +0 -0
  81. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/png.rs +0 -0
  82. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/formats/svg.rs +0 -0
  83. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/mod.rs +0 -0
  84. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/renderer.rs +0 -0
  85. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/shaper.rs +0 -0
  86. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/screenshot/utils.rs +0 -0
  87. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/shell_integration.rs +0 -0
  88. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/sixel.rs +0 -0
  89. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/broadcaster.rs +0 -0
  90. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/client.rs +0 -0
  91. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/error.rs +0 -0
  92. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/mod.rs +0 -0
  93. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/proto.rs +0 -0
  94. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/protocol.rs +0 -0
  95. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/server.rs +0 -0
  96. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/streaming/terminal.pb.rs +0 -0
  97. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/graphics.rs +0 -0
  98. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/notification.rs +0 -0
  99. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/progress.rs +0 -0
  100. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/dcs.rs +0 -0
  101. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/esc.rs +0 -0
  102. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/mod.rs +0 -0
  103. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/sequences/osc.rs +0 -0
  104. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/terminal/write.rs +0 -0
  105. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/text_utils.rs +0 -0
  106. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/tmux_control.rs +0 -0
  107. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/src/unicode_width_config.rs +0 -0
  108. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/theme.css +0 -0
  109. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/__next.__PAGE__.txt +0 -0
  110. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._full.txt +0 -0
  111. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._head.txt +0 -0
  112. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._index.txt +0 -0
  113. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/__next._tree.txt +0 -0
  114. {par_term_emu_core_rust-0.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.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.29.0 → par_term_emu_core_rust-0.30.0}/web_term/_not-found.txt +0 -0
  135. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/favicon.ico +0 -0
  136. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/index.txt +0 -0
  137. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/manifest.json +0 -0
  138. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/web_term/theme.css +0 -0
  139. {par_term_emu_core_rust-0.29.0 → par_term_emu_core_rust-0.30.0}/xterm-issue-draft.md +0 -0
@@ -5,6 +5,25 @@ 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
+
8
27
  ## [0.29.0] - 2026-02-04
9
28
 
10
29
  ### Added
@@ -1767,7 +1767,7 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe"
1767
1767
 
1768
1768
  [[package]]
1769
1769
  name = "par-term-emu-core-rust"
1770
- version = "0.29.0"
1770
+ version = "0.30.0"
1771
1771
  dependencies = [
1772
1772
  "anyhow",
1773
1773
  "axum",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "par-term-emu-core-rust"
3
- version = "0.29.0"
3
+ version = "0.30.0"
4
4
  edition = "2021"
5
5
  rust-version = "1.75"
6
6
  authors = ["Paul Robello <probello@gmail.com>"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: par-term-emu-core-rust
3
- Version: 0.29.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,6 +285,8 @@ 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)
@@ -630,6 +642,8 @@ PtyTerminal(cols: int, rows: int, scrollback: int = 10000)
630
642
 
631
643
  #### Appearance Settings (PTY-Specific)
632
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)
633
647
 
634
648
  **Note:** PtyTerminal inherits all Terminal methods, so you can also use all Terminal appearance settings like `set_default_fg()`, `set_default_bg()`, etc.
635
649
 
@@ -6,7 +6,7 @@ build-backend = "maturin"
6
6
 
7
7
  [project]
8
8
  name = "par-term-emu-core-rust"
9
- version = "0.29.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.29.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.
@@ -554,6 +554,36 @@ impl PyTerminal {
554
554
  Ok(())
555
555
  }
556
556
 
557
+ /// Get modifyOtherKeys mode (XTerm extension for enhanced keyboard input)
558
+ ///
559
+ /// Returns:
560
+ /// Current mode: 0=disabled, 1=report modifiers for special keys, 2=report all keys
561
+ ///
562
+ /// Example:
563
+ /// >>> term.modify_other_keys_mode()
564
+ /// 0
565
+ fn modify_other_keys_mode(&self) -> PyResult<u8> {
566
+ Ok(self.inner.modify_other_keys_mode())
567
+ }
568
+
569
+ /// Set modifyOtherKeys mode (XTerm extension for enhanced keyboard input)
570
+ ///
571
+ /// Args:
572
+ /// mode: 0=disabled, 1=report modifiers for special keys, 2=report all keys
573
+ ///
574
+ /// Note:
575
+ /// Values > 2 are clamped to 2. This directly sets the mode without
576
+ /// sending escape sequences. Use process(b"\\x1b[>4;Nm") to set via sequence.
577
+ ///
578
+ /// Example:
579
+ /// >>> term.set_modify_other_keys_mode(2)
580
+ /// >>> term.modify_other_keys_mode()
581
+ /// 2
582
+ fn set_modify_other_keys_mode(&mut self, mode: u8) -> PyResult<()> {
583
+ self.inner.set_modify_other_keys_mode(mode);
584
+ Ok(())
585
+ }
586
+
557
587
  /// Get clipboard content (OSC 52)
558
588
  ///
559
589
  /// Returns:
@@ -894,6 +924,32 @@ impl PyTerminal {
894
924
  Ok(())
895
925
  }
896
926
 
927
+ /// Get faint/dim text alpha multiplier
928
+ ///
929
+ /// This value is applied to SGR 2 (dim/faint) text during rendering.
930
+ /// A value of 0.5 means 50% opacity (the default).
931
+ ///
932
+ /// Returns:
933
+ /// Alpha multiplier between 0.0 and 1.0
934
+ fn faint_text_alpha(&self) -> PyResult<f32> {
935
+ Ok(self.inner.faint_text_alpha())
936
+ }
937
+
938
+ /// Set faint/dim text alpha multiplier
939
+ ///
940
+ /// This value is applied to SGR 2 (dim/faint) text during rendering.
941
+ /// Values are clamped to the range 0.0-1.0.
942
+ ///
943
+ /// Args:
944
+ /// alpha: Alpha multiplier (0.0 = fully transparent, 1.0 = fully opaque)
945
+ ///
946
+ /// Example:
947
+ /// >>> term.set_faint_text_alpha(0.3) # 30% opacity for dim text
948
+ fn set_faint_text_alpha(&mut self, alpha: f32) -> PyResult<()> {
949
+ self.inner.set_faint_text_alpha(alpha);
950
+ Ok(())
951
+ }
952
+
897
953
  /// Get cursor style (DECSCUSR)
898
954
  ///
899
955
  /// Returns:
@@ -417,6 +417,30 @@ mod tests {
417
417
  assert_eq!(term.smart_cursor_color(), original);
418
418
  }
419
419
 
420
+ #[test]
421
+ fn test_faint_text_alpha_get_set() {
422
+ let mut term = create_test_terminal();
423
+
424
+ // Default should be 0.5
425
+ assert!((term.faint_text_alpha() - 0.5).abs() < f32::EPSILON);
426
+
427
+ // Set to a different value
428
+ term.set_faint_text_alpha(0.3);
429
+ assert!((term.faint_text_alpha() - 0.3).abs() < f32::EPSILON);
430
+
431
+ // Test clamping above 1.0
432
+ term.set_faint_text_alpha(1.5);
433
+ assert!((term.faint_text_alpha() - 1.0).abs() < f32::EPSILON);
434
+
435
+ // Test clamping below 0.0
436
+ term.set_faint_text_alpha(-0.5);
437
+ assert!((term.faint_text_alpha() - 0.0).abs() < f32::EPSILON);
438
+
439
+ // Reset to default
440
+ term.set_faint_text_alpha(0.5);
441
+ assert!((term.faint_text_alpha() - 0.5).abs() < f32::EPSILON);
442
+ }
443
+
420
444
  #[test]
421
445
  fn test_set_ansi_palette_color_valid_indices() {
422
446
  let mut term = create_test_terminal();
@@ -1181,6 +1181,9 @@ pub struct Terminal {
1181
1181
  keyboard_stack: Vec<u16>,
1182
1182
  /// Stack for keyboard protocol flags (alternate screen)
1183
1183
  keyboard_stack_alt: Vec<u16>,
1184
+ /// modifyOtherKeys mode (XTerm extension for enhanced keyboard input)
1185
+ /// 0 = disabled, 1 = report modifiers for special keys, 2 = report modifiers for all keys
1186
+ modify_other_keys_mode: u8,
1184
1187
  /// Response buffer for device queries (DA/DSR/etc)
1185
1188
  response_buffer: Vec<u8>,
1186
1189
  /// Hyperlink storage: ID -> URL mapping (for deduplication)
@@ -1275,6 +1278,9 @@ pub struct Terminal {
1275
1278
  use_selected_text_color: bool,
1276
1279
  /// Smart cursor color - auto-adjust based on background (iTerm2: "Smart Cursor Color")
1277
1280
  smart_cursor_color: bool,
1281
+ /// Faint/dim text alpha multiplier (0.0-1.0, default 0.5)
1282
+ /// Applied to SGR 2 (dim) text during rendering
1283
+ faint_text_alpha: f32,
1278
1284
  /// Attribute change extent mode (DECSACE) - 0/1: stream, 2: rectangle (default)
1279
1285
  attribute_change_extent: u8,
1280
1286
  /// Terminal conformance level (VT100/VT220/VT320/VT420/VT520)
@@ -1608,6 +1614,7 @@ impl Terminal {
1608
1614
  keyboard_flags: 0,
1609
1615
  keyboard_stack: Vec::new(),
1610
1616
  keyboard_stack_alt: Vec::new(),
1617
+ modify_other_keys_mode: 0,
1611
1618
  response_buffer: Vec::new(),
1612
1619
  hyperlinks: HashMap::new(),
1613
1620
  current_hyperlink_id: None,
@@ -1658,6 +1665,7 @@ impl Terminal {
1658
1665
  use_cursor_guide: false,
1659
1666
  use_selected_text_color: false,
1660
1667
  smart_cursor_color: false,
1668
+ faint_text_alpha: 0.5, // 50% dimming for SGR 2 (faint/dim) text
1661
1669
  // VT420 attribute change extent mode - default to rectangle (2)
1662
1670
  attribute_change_extent: 2,
1663
1671
  // VT520 conformance level - default to VT520 for maximum compatibility
@@ -2006,6 +2014,8 @@ impl Terminal {
2006
2014
  // TUI apps may enable Kitty keyboard protocol and fail to disable it on exit
2007
2015
  self.keyboard_flags = 0;
2008
2016
  self.keyboard_stack_alt.clear();
2017
+ // Also reset modifyOtherKeys mode
2018
+ self.modify_other_keys_mode = 0;
2009
2019
  }
2010
2020
  }
2011
2021
 
@@ -2065,6 +2075,18 @@ impl Terminal {
2065
2075
  self.bold_brightening = enabled;
2066
2076
  }
2067
2077
 
2078
+ /// Get faint/dim text alpha multiplier (0.0-1.0)
2079
+ /// Applied to SGR 2 (dim) text during rendering
2080
+ pub fn faint_text_alpha(&self) -> f32 {
2081
+ self.faint_text_alpha
2082
+ }
2083
+
2084
+ /// Set faint/dim text alpha multiplier (0.0-1.0)
2085
+ /// Values are clamped to valid range
2086
+ pub fn set_faint_text_alpha(&mut self, alpha: f32) {
2087
+ self.faint_text_alpha = alpha.clamp(0.0, 1.0);
2088
+ }
2089
+
2068
2090
  /// Get shell integration state
2069
2091
  pub fn shell_integration(&self) -> &ShellIntegration {
2070
2092
  &self.shell_integration
@@ -2258,6 +2280,18 @@ impl Terminal {
2258
2280
  self.keyboard_flags = flags;
2259
2281
  }
2260
2282
 
2283
+ /// Get modifyOtherKeys mode (XTerm extension)
2284
+ /// 0 = disabled, 1 = report modifiers for special keys, 2 = report modifiers for all keys
2285
+ pub fn modify_other_keys_mode(&self) -> u8 {
2286
+ self.modify_other_keys_mode
2287
+ }
2288
+
2289
+ /// Set modifyOtherKeys mode (for testing/direct control)
2290
+ pub fn set_modify_other_keys_mode(&mut self, mode: u8) {
2291
+ // Clamp to valid range (0-2)
2292
+ self.modify_other_keys_mode = mode.min(2);
2293
+ }
2294
+
2261
2295
  /// Get clipboard content (OSC 52)
2262
2296
  pub fn clipboard(&self) -> Option<&str> {
2263
2297
  self.clipboard_content.as_deref()
@@ -3035,6 +3069,7 @@ impl Terminal {
3035
3069
  self.keyboard_flags = 0;
3036
3070
  self.keyboard_stack.clear();
3037
3071
  self.keyboard_stack_alt.clear();
3072
+ self.modify_other_keys_mode = 0;
3038
3073
  self.response_buffer.clear();
3039
3074
  self.hyperlinks.clear();
3040
3075
  self.current_hyperlink_id = None;
@@ -3561,6 +3596,7 @@ impl Terminal {
3561
3596
  }
3562
3597
  config.use_bold_color = self.use_bold_color;
3563
3598
  config.bold_brightening = self.bold_brightening;
3599
+ config.faint_text_alpha = self.faint_text_alpha;
3564
3600
 
3565
3601
  // Use terminal's default background if not specified
3566
3602
  if config.background_color.is_none() {
@@ -3610,6 +3646,7 @@ impl Terminal {
3610
3646
  }
3611
3647
  config.use_bold_color = self.use_bold_color;
3612
3648
  config.bold_brightening = self.bold_brightening;
3649
+ config.faint_text_alpha = self.faint_text_alpha;
3613
3650
 
3614
3651
  // Use terminal's default background if not specified
3615
3652
  if config.background_color.is_none() {
@@ -221,6 +221,63 @@ impl Terminal {
221
221
  self.adjust_graphics_for_scroll_down(n, top, bottom);
222
222
  }
223
223
  'm' => {
224
+ // Check for modifyOtherKeys mode setting: CSI > 4 ; mode m
225
+ if intermediates.contains(&b'>') {
226
+ // modifyOtherKeys mode setting: CSI > 4 ; mode m
227
+ let mut param_iter = params.iter();
228
+ let first_param = param_iter
229
+ .next()
230
+ .and_then(|p| p.first())
231
+ .copied()
232
+ .unwrap_or(0);
233
+
234
+ if first_param == 4 {
235
+ // CSI > 4 ; mode m - Set modifyOtherKeys mode
236
+ let mode = param_iter
237
+ .next()
238
+ .and_then(|p| p.first())
239
+ .copied()
240
+ .unwrap_or(0) as u8;
241
+ // Clamp to valid range (0-2)
242
+ self.modify_other_keys_mode = mode.min(2);
243
+ debug::log(
244
+ debug::DebugLevel::Info,
245
+ "CSI",
246
+ &format!(
247
+ "modifyOtherKeys mode set to {}",
248
+ self.modify_other_keys_mode
249
+ ),
250
+ );
251
+ }
252
+ return;
253
+ }
254
+
255
+ // Check for modifyOtherKeys query: CSI ? 4 m
256
+ if private {
257
+ let param = params
258
+ .iter()
259
+ .next()
260
+ .and_then(|p| p.first())
261
+ .copied()
262
+ .unwrap_or(0);
263
+
264
+ if param == 4 {
265
+ // CSI ? 4 m - Query modifyOtherKeys mode
266
+ // Response: CSI > 4 ; mode m
267
+ let response = format!("\x1b[>4;{}m", self.modify_other_keys_mode);
268
+ self.push_response(response.as_bytes());
269
+ debug::log(
270
+ debug::DebugLevel::Info,
271
+ "CSI",
272
+ &format!(
273
+ "modifyOtherKeys query, responding with mode {}",
274
+ self.modify_other_keys_mode
275
+ ),
276
+ );
277
+ }
278
+ return;
279
+ }
280
+
224
281
  // SGR - Select Graphic Rendition
225
282
  // Debug: Log SGR parameters for TMUX status bar debugging
226
283
  if crate::debug::is_enabled(crate::debug::DebugLevel::Info) && !params.is_empty() {
@@ -117,7 +117,7 @@ wheels = [
117
117
 
118
118
  [[package]]
119
119
  name = "par-term-emu-core-rust"
120
- version = "0.29.0"
120
+ version = "0.30.0"
121
121
  source = { editable = "." }
122
122
  dependencies = [
123
123
  { name = "pillow" },