1
- use std:: { env, fmt:: Display , io :: { Read , Write } , path:: Path , sync:: Arc } ;
1
+ use std:: { env, fmt:: Display , path:: Path , sync:: Arc } ;
2
2
3
- use anyhow:: { anyhow, Result } ;
4
- use crossterm:: terminal:: { disable_raw_mode, enable_raw_mode} ;
3
+ use anyhow:: Result ;
5
4
use ratatui:: layout:: Rect ;
6
5
use tracing:: warn;
7
6
use yazi_shared:: { env_exists, term:: Term } ;
8
7
9
8
use super :: { Iterm2 , Kitty , KittyOld } ;
10
- use crate :: { ueberzug:: Ueberzug , Sixel , SHOWN , TMUX } ;
9
+ use crate :: { ueberzug:: Ueberzug , Emulator , Sixel , SHOWN , TMUX } ;
11
10
12
11
#[ derive( Clone , Copy , PartialEq , Eq , Debug ) ]
13
12
pub enum Adaptor {
@@ -22,181 +21,6 @@ pub enum Adaptor {
22
21
Chafa ,
23
22
}
24
23
25
- #[ derive( Clone ) ]
26
- enum Emulator {
27
- Unknown ( Vec < Adaptor > ) ,
28
- Kitty ,
29
- Konsole ,
30
- Iterm2 ,
31
- WezTerm ,
32
- Foot ,
33
- Ghostty ,
34
- BlackBox ,
35
- VSCode ,
36
- Tabby ,
37
- Hyper ,
38
- Mintty ,
39
- Neovim ,
40
- }
41
-
42
- impl Adaptor {
43
- fn emulator ( ) -> Emulator {
44
- if env_exists ( "NVIM_LOG_FILE" ) && env_exists ( "NVIM" ) {
45
- return Emulator :: Neovim ;
46
- }
47
-
48
- let vars = [
49
- ( "KITTY_WINDOW_ID" , Emulator :: Kitty ) ,
50
- ( "KONSOLE_VERSION" , Emulator :: Konsole ) ,
51
- ( "ITERM_SESSION_ID" , Emulator :: Iterm2 ) ,
52
- ( "WEZTERM_EXECUTABLE" , Emulator :: WezTerm ) ,
53
- ( "GHOSTTY_RESOURCES_DIR" , Emulator :: Ghostty ) ,
54
- ( "VSCODE_INJECTION" , Emulator :: VSCode ) ,
55
- ( "TABBY_CONFIG_DIRECTORY" , Emulator :: Tabby ) ,
56
- ] ;
57
- match vars. into_iter ( ) . find ( |v| env_exists ( v. 0 ) ) {
58
- Some ( var) => return var. 1 ,
59
- None => warn ! ( "[Adaptor] No special environment variables detected" ) ,
60
- }
61
-
62
- let ( term, program) = Self :: via_env ( ) ;
63
- match program. as_str ( ) {
64
- "iTerm.app" => return Emulator :: Iterm2 ,
65
- "WezTerm" => return Emulator :: WezTerm ,
66
- "ghostty" => return Emulator :: Ghostty ,
67
- "BlackBox" => return Emulator :: BlackBox ,
68
- "vscode" => return Emulator :: VSCode ,
69
- "Tabby" => return Emulator :: Tabby ,
70
- "Hyper" => return Emulator :: Hyper ,
71
- "mintty" => return Emulator :: Mintty ,
72
- _ => warn ! ( "[Adaptor] Unknown TERM_PROGRAM: {program}" ) ,
73
- }
74
- match term. as_str ( ) {
75
- "xterm-kitty" => return Emulator :: Kitty ,
76
- "foot" => return Emulator :: Foot ,
77
- "foot-extra" => return Emulator :: Foot ,
78
- "xterm-ghostty" => return Emulator :: Ghostty ,
79
- _ => warn ! ( "[Adaptor] Unknown TERM: {term}" ) ,
80
- }
81
-
82
- Self :: via_csi ( ) . unwrap_or ( Emulator :: Unknown ( vec ! [ ] ) )
83
- }
84
-
85
- pub ( super ) fn detect ( ) -> Self {
86
- let mut protocols = match Self :: emulator ( ) {
87
- Emulator :: Unknown ( adapters) => adapters,
88
- Emulator :: Kitty => vec ! [ Self :: Kitty ] ,
89
- Emulator :: Konsole => vec ! [ Self :: KittyOld , Self :: Iterm2 , Self :: Sixel ] ,
90
- Emulator :: Iterm2 => vec ! [ Self :: Iterm2 , Self :: Sixel ] ,
91
- Emulator :: WezTerm => vec ! [ Self :: Iterm2 , Self :: Sixel ] ,
92
- Emulator :: Foot => vec ! [ Self :: Sixel ] ,
93
- Emulator :: Ghostty => vec ! [ Self :: KittyOld ] ,
94
- Emulator :: BlackBox => vec ! [ Self :: Sixel ] ,
95
- Emulator :: VSCode => vec ! [ Self :: Iterm2 , Self :: Sixel ] ,
96
- Emulator :: Tabby => vec ! [ Self :: Iterm2 , Self :: Sixel ] ,
97
- Emulator :: Hyper => vec ! [ Self :: Iterm2 , Self :: Sixel ] ,
98
- Emulator :: Mintty => vec ! [ Self :: Iterm2 ] ,
99
- Emulator :: Neovim => vec ! [ ] ,
100
- } ;
101
-
102
- #[ cfg( windows) ]
103
- protocols. retain ( |p| * p == Self :: Iterm2 ) ;
104
- if env_exists ( "ZELLIJ_SESSION_NAME" ) {
105
- protocols. retain ( |p| * p == Self :: Sixel ) ;
106
- }
107
- if * TMUX && protocols. len ( ) > 1 {
108
- protocols. retain ( |p| * p != Self :: KittyOld ) ;
109
- }
110
- if let Some ( p) = protocols. first ( ) {
111
- return * p;
112
- }
113
-
114
- match env:: var ( "XDG_SESSION_TYPE" ) . unwrap_or_default ( ) . as_str ( ) {
115
- "x11" => return Self :: X11 ,
116
- "wayland" => return Self :: Wayland ,
117
- _ => warn ! ( "[Adaptor] Could not identify XDG_SESSION_TYPE" ) ,
118
- }
119
- if env_exists ( "WAYLAND_DISPLAY" ) {
120
- return Self :: Wayland ;
121
- }
122
- if env_exists ( "DISPLAY" ) {
123
- return Self :: X11 ;
124
- }
125
- if std:: fs:: symlink_metadata ( "/proc/sys/fs/binfmt_misc/WSLInterop" ) . is_ok ( ) {
126
- return Self :: KittyOld ;
127
- }
128
-
129
- warn ! ( "[Adaptor] Falling back to chafa" ) ;
130
- Self :: Chafa
131
- }
132
-
133
- fn via_env ( ) -> ( String , String ) {
134
- fn tmux_env ( name : & str ) -> Result < String > {
135
- let output = std:: process:: Command :: new ( "tmux" ) . args ( [ "show-environment" , name] ) . output ( ) ?;
136
-
137
- String :: from_utf8 ( output. stdout ) ?
138
- . trim ( )
139
- . strip_prefix ( & format ! ( "{name}=" ) )
140
- . map_or_else ( || Err ( anyhow ! ( "" ) ) , |s| Ok ( s. to_string ( ) ) )
141
- }
142
-
143
- let mut term = env:: var ( "TERM" ) . unwrap_or_default ( ) ;
144
- let mut program = env:: var ( "TERM_PROGRAM" ) . unwrap_or_default ( ) ;
145
-
146
- if * TMUX {
147
- term = tmux_env ( "TERM" ) . unwrap_or ( term) ;
148
- program = tmux_env ( "TERM_PROGRAM" ) . unwrap_or ( program) ;
149
- }
150
-
151
- ( term, program)
152
- }
153
-
154
- fn via_csi ( ) -> Result < Emulator > {
155
- enable_raw_mode ( ) ?;
156
- std:: io:: stdout ( ) . write_all ( b"\x1b [>q\x1b _Gi=31,s=1,v=1,a=q,t=d,f=24;AAAA\x1b \\ \x1b [c" ) ?;
157
- std:: io:: stdout ( ) . flush ( ) ?;
158
-
159
- let mut stdin = std:: io:: stdin ( ) . lock ( ) ;
160
- let mut buf = String :: with_capacity ( 200 ) ;
161
- loop {
162
- let mut c = [ 0 ; 1 ] ;
163
- if stdin. read ( & mut c) ? == 0 {
164
- break ;
165
- }
166
- if c[ 0 ] == b'c' && buf. contains ( "\x1b [?" ) {
167
- break ;
168
- }
169
- buf. push ( c[ 0 ] as char ) ;
170
- }
171
-
172
- disable_raw_mode ( ) . ok ( ) ;
173
- let names = [
174
- ( "kitty" , Emulator :: Kitty ) ,
175
- ( "Konsole" , Emulator :: Konsole ) ,
176
- ( "iTerm2" , Emulator :: Iterm2 ) ,
177
- ( "WezTerm" , Emulator :: WezTerm ) ,
178
- ( "foot" , Emulator :: Foot ) ,
179
- ( "ghostty" , Emulator :: Ghostty ) ,
180
- ] ;
181
-
182
- for ( name, emulator) in names. iter ( ) {
183
- if buf. contains ( name) {
184
- return Ok ( emulator. clone ( ) ) ;
185
- }
186
- }
187
-
188
- let mut adapters = Vec :: with_capacity ( 2 ) ;
189
- if buf. contains ( "\x1b _Gi=31;OK" ) {
190
- adapters. push ( Adaptor :: KittyOld ) ;
191
- }
192
- if [ "?4;" , "?4c" , ";4;" , ";4c" ] . iter ( ) . any ( |s| buf. contains ( s) ) {
193
- adapters. push ( Adaptor :: Sixel ) ;
194
- }
195
-
196
- Ok ( Emulator :: Unknown ( adapters) )
197
- }
198
- }
199
-
200
24
impl Display for Adaptor {
201
25
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
202
26
match self {
@@ -212,8 +36,6 @@ impl Display for Adaptor {
212
36
}
213
37
214
38
impl Adaptor {
215
- pub ( super ) fn start ( self ) { Ueberzug :: start ( self ) ; }
216
-
217
39
pub async fn image_show ( self , path : & Path , rect : Rect ) -> Result < ( u32 , u32 ) > {
218
40
match self {
219
41
Self :: Kitty => Kitty :: image_show ( path, rect) . await ,
@@ -241,6 +63,8 @@ impl Adaptor {
241
63
#[ inline]
242
64
pub fn shown_load ( self ) -> Option < Rect > { SHOWN . load_full ( ) . map ( |r| * r) }
243
65
66
+ pub ( super ) fn start ( self ) { Ueberzug :: start ( self ) ; }
67
+
244
68
#[ inline]
245
69
pub ( super ) fn shown_store ( rect : Rect , size : ( u32 , u32 ) ) {
246
70
SHOWN . store ( Some ( Arc :: new (
@@ -260,3 +84,39 @@ impl Adaptor {
260
84
!matches ! ( self , Self :: Kitty | Self :: KittyOld | Self :: Iterm2 | Self :: Sixel )
261
85
}
262
86
}
87
+
88
+ impl Adaptor {
89
+ pub fn matches ( ) -> Self {
90
+ let mut protocols = Emulator :: detect ( ) . adapters ( ) ;
91
+
92
+ #[ cfg( windows) ]
93
+ protocols. retain ( |p| * p == Self :: Iterm2 ) ;
94
+ if env_exists ( "ZELLIJ_SESSION_NAME" ) {
95
+ protocols. retain ( |p| * p == Self :: Sixel ) ;
96
+ }
97
+ if * TMUX && protocols. len ( ) > 1 {
98
+ protocols. retain ( |p| * p != Self :: KittyOld ) ;
99
+ }
100
+ if let Some ( p) = protocols. first ( ) {
101
+ return * p;
102
+ }
103
+
104
+ match env:: var ( "XDG_SESSION_TYPE" ) . unwrap_or_default ( ) . as_str ( ) {
105
+ "x11" => return Self :: X11 ,
106
+ "wayland" => return Self :: Wayland ,
107
+ _ => warn ! ( "[Adaptor] Could not identify XDG_SESSION_TYPE" ) ,
108
+ }
109
+ if env_exists ( "WAYLAND_DISPLAY" ) {
110
+ return Self :: Wayland ;
111
+ }
112
+ if env_exists ( "DISPLAY" ) {
113
+ return Self :: X11 ;
114
+ }
115
+ if std:: fs:: symlink_metadata ( "/proc/sys/fs/binfmt_misc/WSLInterop" ) . is_ok ( ) {
116
+ return Self :: KittyOld ;
117
+ }
118
+
119
+ warn ! ( "[Adaptor] Falling back to chafa" ) ;
120
+ Self :: Chafa
121
+ }
122
+ }
0 commit comments