Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iterm2 image protocol #661

Merged
merged 7 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ sugarloaf = { path = "sugarloaf", version = "0.1.12" }
corcovado = { path = "corcovado", version = "0.1.12" }
rio-config = { path = "rio-config", version = "0.1.12" }
rio-proc-macros = { path = "rio-proc-macros", version = "0.1.12" }
copa = { path = "copa", default-features = true, version = "0.1.12" }
copa = { path = "copa", default-features = false, version = "0.1.12" }
teletypewriter = { path = "teletypewriter", version = "0.1.12" }
rio-backend = { path = "rio-backend", version = "0.1.12" }
rio-window = { path = "rio-window", version = "0.1.12", default-features = false }
Expand All @@ -41,7 +41,8 @@ raw-window-handle = { version = "0.6.2", features = ["std"] }
parking_lot = { version = "0.12.3", features = ["nightly", "hardware-lock-elision"] }
rustc-hash = "2.0.0"
unicode-width = "0.1.13"
image_rs = { package = "image", version = "0.25.2", default-features = false, features = ["ico"] }
base64 = "0.22.1"
image_rs = { package = "image", version = "0.25.2", default-features = false, features = ["gif", "jpeg", "ico", "png", "pnm", "webp", "bmp"] }
regex = "1.10.5"
bytemuck = { version = "1.17.0", features = [ "derive" ] }
swash = "0.1.18"
Expand Down
3 changes: 0 additions & 3 deletions copa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ edition = "2021"
rio-proc-macros = { workspace = true }
arrayvec = { version = "0.7.6", default-features = false, optional = true }

[dev-dependencies]
unicode-normalization = "0.1.22"

[features]
default = ["no_std"]
no_std = ["arrayvec"]
Expand Down
58 changes: 29 additions & 29 deletions copa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -657,35 +657,35 @@ mod tests {
}
}

#[test]
fn issue_191() {
use crate::std::string::{String, ToString};
use unicode_normalization::{is_nfc_quick, IsNormalized, UnicodeNormalization};

// https://github.com/raphamorim/rio/issues/191
// 한 isn't rendered correctly via printf '\xe1\x84\x92\xe1\x85\xa1\xe1\x86\xab\n'
let mut input =
std::str::from_utf8(b"\xe1\x84\x92\xe1\x85\xa1\xe1\x86\xab").unwrap();
let mut dispatcher = Dispatcher::default();
let mut parser = Parser::new();

let p = std::mem::take(&mut input).to_string();
let normalized: String;
let text = if is_nfc_quick(p.chars()) == IsNormalized::Yes {
p.as_str()
} else {
normalized = p.as_str().nfc().collect();
normalized.as_str()
};

let bytes: &[u8] = &text.bytes().collect::<Vec<u8>>();

for byte in bytes {
parser.advance(&mut dispatcher, *byte);
}

assert_eq!(text, "한");
}
// #[test]
// fn issue_191() {
// use crate::std::string::{String, ToString};
// use unicode_normalization::{is_nfc_quick, IsNormalized, UnicodeNormalization};

// // https://github.com/raphamorim/rio/issues/191
// // 한 isn't rendered correctly via printf '\xe1\x84\x92\xe1\x85\xa1\xe1\x86\xab\n'
// let mut input =
// std::str::from_utf8(b"\xe1\x84\x92\xe1\x85\xa1\xe1\x86\xab").unwrap();
// let mut dispatcher = Dispatcher::default();
// let mut parser = Parser::new();

// let p = std::mem::take(&mut input).to_string();
// let normalized: String;
// let text = if is_nfc_quick(p.chars()) == IsNormalized::Yes {
// p.as_str()
// } else {
// normalized = p.as_str().nfc().collect();
// normalized.as_str()
// };

// let bytes: &[u8] = &text.bytes().collect::<Vec<u8>>();

// for byte in bytes {
// parser.advance(&mut dispatcher, *byte);
// }

// assert_eq!(text, "한");
// }

#[test]
fn exceed_max_buffer_size() {
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/features/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Short introduction of Rio terminal features.

- [Vi mode](/docs/features/vi-mode)
- [Hyperlinks](/docs/features/hyperlinks)
- [iTerm image protocol](/docs/features/iterm-image-protocol)
- [iTerm2 image protocol](/docs/features/iterm2-image-protocol)
- [Kitty keyboard protocol](/docs/features/kitty-keyboard-protocol)
- [Rio is fast](/docs/features/rio-is-fast)
- [Adaptive theme](/docs/features/adaptive-theme)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
---
title: 'iTerm Image Protocol'
title: 'iTerm2 Image Protocol'
language: 'en'
---

**Note: iTerm Image Protocol is still under development**

Rio implements support for the iTerm2 inline image protocol.

To render an image inline in your terminal, you can use `imgcat` provided as a script by iTerm2 in [iterm2.com/utilities/imgcat](https://iterm2.com/utilities/imgcat) or from other sources like:
Expand All @@ -14,8 +12,6 @@ To render an image inline in your terminal, you can use `imgcat` provided as a s
- [npmjs.com/package/imgcat](https://www.npmjs.com/package/imgcat)
- ... and etecetera.

```bash
imgcat ./rio-logo.png
```
![Demo iTerm2 image protocol](/assets/features/demo-iterm2-image-protocol.png)

More info about [iTerm image protocol](https://iterm2.com/documentation-images.html)
More info regarding [iTerm image protocol](https://iterm2.com/documentation-images.html)
1 change: 1 addition & 0 deletions docs/docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ language: 'en'
<!-- - Fix: MacOS Delete key doesn't work in kitty mode [#513](https://github.com/raphamorim/rio/issues/513). -->
<!-- - Fix: Kitty keyboard protocol doesn't work with tmux [#599](https://github.com/raphamorim/rio/issues/599). -->

- Support to iTerm2 image protocol.
- Fix: Issue building rio for Void Linux [#656](https://github.com/raphamorim/rio/issues/656).
- Fix: Adaptive theme doesn't appear to work correctly on macOS [#660](https://github.com/raphamorim/rio/issues/660).
- Fix: Image background support to OpenGL targets.
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 7 additions & 7 deletions frontends/rioterm/src/bindings/kitty_keyboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ pub fn build_key_sequence(key: &KeyEvent, mods: ModifiersState, mode: Mode) -> V
let mut modifiers = mods.into();

let kitty_seq = mode.intersects(
Mode::KEYBOARD_REPORT_ALL_KEYS_AS_ESC
| Mode::KEYBOARD_DISAMBIGUATE_ESC_CODES
| Mode::KEYBOARD_REPORT_EVENT_TYPES,
Mode::REPORT_ALL_KEYS_AS_ESC
| Mode::DISAMBIGUATE_ESC_CODES
| Mode::REPORT_EVENT_TYPES,
);

let kitty_encode_all = mode.contains(Mode::KEYBOARD_REPORT_ALL_KEYS_AS_ESC);
let kitty_encode_all = mode.contains(Mode::REPORT_ALL_KEYS_AS_ESC);
// The default parameter is 1, so we can omit it.
let kitty_event_type = mode.contains(Mode::KEYBOARD_REPORT_EVENT_TYPES)
let kitty_event_type = mode.contains(Mode::REPORT_EVENT_TYPES)
&& (key.repeat || key.state == ElementState::Released);

let context = SequenceBuilder {
Expand All @@ -47,7 +47,7 @@ pub fn build_key_sequence(key: &KeyEvent, mods: ModifiersState, mode: Mode) -> V
let text = key.text_with_all_modifiers();

let associated_text = text.filter(|text| {
mode.contains(Mode::KEYBOARD_REPORT_ASSOCIATED_TEXT)
mode.contains(Mode::REPORT_ASSOCIATED_TEXT)
&& key.state != ElementState::Released
&& !text.is_empty()
&& !is_control_character(text)
Expand Down Expand Up @@ -143,7 +143,7 @@ impl SequenceBuilder {

// NOTE: Base layouts are ignored, since winit doesn't expose this information
// yet.
let payload = if self.mode.contains(Mode::KEYBOARD_REPORT_ALTERNATE_KEYS)
let payload = if self.mode.contains(Mode::REPORT_ALTERNATE_KEYS)
&& alternate_key_code != unicode_key_code
{
format!("{unicode_key_code}:{alternate_key_code}")
Expand Down
4 changes: 2 additions & 2 deletions frontends/rioterm/src/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,11 @@ impl BindingMode {
binding_mode.set(BindingMode::SEARCH, search);
binding_mode.set(
BindingMode::DISAMBIGUATE_KEYS,
mode.contains(Mode::KEYBOARD_DISAMBIGUATE_ESC_CODES),
mode.contains(Mode::DISAMBIGUATE_ESC_CODES),
);
binding_mode.set(
BindingMode::ALL_KEYS_AS_ESC,
mode.contains(Mode::KEYBOARD_REPORT_ALL_KEYS_AS_ESC),
mode.contains(Mode::REPORT_ALL_KEYS_AS_ESC),
);
binding_mode.set(BindingMode::VI, mode.contains(Mode::VI));
binding_mode
Expand Down
10 changes: 5 additions & 5 deletions frontends/rioterm/src/screen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ impl Screen<'_> {
let mods = self.modifiers.state();

if is_kitty_keyboard_enabled && key.state == ElementState::Released {
if !mode.contains(Mode::KEYBOARD_REPORT_EVENT_TYPES)
if !mode.contains(Mode::REPORT_EVENT_TYPES)
|| mode.contains(Mode::VI)
|| self.search_active()
{
Expand All @@ -476,7 +476,7 @@ impl Screen<'_> {
// NOTE: Echo the key back on release to follow kitty/foot behavior. When
// KEYBOARD_REPORT_ALL_KEYS_AS_ESC is used, we build proper escapes for
// the keys below.
_ if mode.contains(Mode::KEYBOARD_REPORT_ALL_KEYS_AS_ESC) => {
_ if mode.contains(Mode::REPORT_ALL_KEYS_AS_ESC) => {
crate::bindings::kitty_keyboard::build_key_sequence(key, mods, mode)
.into()
}
Expand Down Expand Up @@ -533,10 +533,10 @@ impl Screen<'_> {
// 1. No keyboard input protocol is enabled.
// 2. Mode is KEYBOARD_DISAMBIGUATE_ESC_CODES, but we have text + empty or Shift
// modifiers and the location of the key is not on the numpad, and it's not an `Esc`.
let write_legacy = !mode.contains(Mode::KEYBOARD_REPORT_ALL_KEYS_AS_ESC)
let write_legacy = !mode.contains(Mode::REPORT_ALL_KEYS_AS_ESC)
&& !text.is_empty()
&& (!mode.contains(Mode::KEYBOARD_DISAMBIGUATE_ESC_CODES)
|| (mode.contains(Mode::KEYBOARD_DISAMBIGUATE_ESC_CODES)
&& (!mode.contains(Mode::DISAMBIGUATE_ESC_CODES)
|| (mode.contains(Mode::DISAMBIGUATE_ESC_CODES)
&& (mods.is_empty() || mods == ModifiersState::SHIFT)
&& key.location != KeyLocation::Numpad
// Special case escape here.
Expand Down
3 changes: 2 additions & 1 deletion rio-backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ tracing = { workspace = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
toml = "0.8.19"
base64 = "0.22.1"
base64 = { workspace = true }
bitflags = { workspace = true }
bytemuck = { workspace = true }
corcovado = { workspace = true }
rustc-hash = { workspace = true }
regex = { workspace = true }
raw-window-handle = { workspace = true }
copypasta = { version = "0.10.1", default-features = false }
Expand Down
11 changes: 7 additions & 4 deletions rio-backend/src/ansi/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Alacritty is licensed under Apache 2.0 license.
// https://github.com/alacritty/alacritty/pull/4763/files

use crate::ansi::sixel;
use crate::config::colors::ColorRgb;
use crate::crosswords::grid::Dimensions;
use crate::sugarloaf::{GraphicData, GraphicId};
Expand Down Expand Up @@ -33,9 +34,6 @@ pub struct UpdateQueues {
pub clear_subregions: Vec<ClearSubregion>,
}

/// Max allowed dimensions (width, height) for the graphic, in pixels.
pub const MAX_GRAPHIC_DIMENSIONS: [usize; 2] = [4096, 4096];

#[derive(Clone, Debug)]
pub struct TextureRef {
/// Graphic identifier.
Expand Down Expand Up @@ -127,7 +125,7 @@ pub enum TextureOperation {
}

/// Track changes in the grid to add or to remove graphics.
#[derive(Clone, Debug, Default)]
#[derive(Debug, Default)]
pub struct Graphics {
/// Last generated identifier.
pub last_id: u64,
Expand All @@ -146,6 +144,9 @@ pub struct Graphics {

/// Cell width in pixels.
pub cell_width: f32,

/// Current Sixel parser.
pub sixel_parser: Option<Box<sixel::Parser>>,
}

impl Graphics {
Expand Down Expand Up @@ -214,6 +215,7 @@ fn check_opaque_region() {
color_type: ColorType::Rgb,
pixels: vec![255; 10 * 10 * 3],
is_opaque: true,
resize: None,
};

assert!(graphic.is_filled(1, 1, 3, 3));
Expand All @@ -236,6 +238,7 @@ fn check_opaque_region() {
height: 10,
color_type: ColorType::Rgba,
is_opaque: false,
resize: None,
};

assert!(graphic.is_filled(0, 0, 3, 3));
Expand Down
Loading
Loading