@@ -4,13 +4,16 @@ use crossterm::{
4
4
execute, queue,
5
5
style:: {
6
6
Attribute as CAttribute , Color as CColor , Print , SetAttribute , SetBackgroundColor ,
7
- SetForegroundColor , SetUnderlineColor ,
7
+ SetForegroundColor ,
8
8
} ,
9
9
terminal:: { self , Clear , ClearType } ,
10
+ Command ,
10
11
} ;
11
12
use helix_view:: graphics:: { Color , CursorKind , Modifier , Rect , UnderlineStyle } ;
12
- use std:: io:: { self , Write } ;
13
-
13
+ use std:: {
14
+ fmt,
15
+ io:: { self , Write } ,
16
+ } ;
14
17
fn vte_version ( ) -> Option < usize > {
15
18
std:: env:: var ( "VTE_VERSION" ) . ok ( ) ?. parse ( ) . ok ( )
16
19
}
@@ -108,18 +111,19 @@ where
108
111
map_error ( queue ! ( self . buffer, SetBackgroundColor ( color) ) ) ?;
109
112
bg = cell. bg ;
110
113
}
111
- if cell. underline_color != underline_color {
112
- let color = CColor :: from ( cell. underline_color ) ;
113
- map_error ( queue ! ( self . buffer, SetUnderlineColor ( color) ) ) ?;
114
- underline_color = cell. underline_color ;
115
- }
116
114
117
115
let mut new_underline_style = cell. underline_style ;
118
116
if !self . capabilities . has_extended_underlines {
119
117
match new_underline_style {
120
- UnderlineStyle :: Reset => ( ) ,
118
+ UnderlineStyle :: Reset | UnderlineStyle :: Line => ( ) ,
121
119
_ => new_underline_style = UnderlineStyle :: Line ,
122
120
}
121
+
122
+ if cell. underline_color != underline_color {
123
+ let color = CColor :: from ( cell. underline_color ) ;
124
+ map_error ( queue ! ( self . buffer, SetUnderlineColor ( color) ) ) ?;
125
+ underline_color = cell. underline_color ;
126
+ }
123
127
}
124
128
125
129
if new_underline_style != underline_style {
@@ -244,3 +248,58 @@ impl ModifierDiff {
244
248
Ok ( ( ) )
245
249
}
246
250
}
251
+
252
+ /// Crossterm uses semicolon as a seperator for colors
253
+ /// this is actually not spec compliant (altough commonly supported)
254
+ /// However the correct approach is to use colons as a seperator.
255
+ /// This usually doesn't make a difference for emulators that do support colored underlines.
256
+ /// However terminals that do not support colored underlines will ignore underlines colors with colons
257
+ /// while escape sequences with semicolons are always processed which leads to weird visual artifacts.
258
+ /// See [this nvim issue](https://github.com/neovim/neovim/issues/9270) for details
259
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
260
+ pub struct SetUnderlineColor ( pub CColor ) ;
261
+
262
+ impl Command for SetUnderlineColor {
263
+ fn write_ansi ( & self , f : & mut impl fmt:: Write ) -> fmt:: Result {
264
+ let color = self . 0 ;
265
+
266
+ if color == CColor :: Reset {
267
+ write ! ( f, "\x1b [59m" ) ?;
268
+ return Ok ( ( ) ) ;
269
+ }
270
+ f. write_str ( "\x1b [58:" ) ?;
271
+
272
+ let res = match color {
273
+ CColor :: Black => f. write_str ( "5:0" ) ,
274
+ CColor :: DarkGrey => f. write_str ( "5:8" ) ,
275
+ CColor :: Red => f. write_str ( "5:9" ) ,
276
+ CColor :: DarkRed => f. write_str ( "5:1" ) ,
277
+ CColor :: Green => f. write_str ( "5:10" ) ,
278
+ CColor :: DarkGreen => f. write_str ( "5:2" ) ,
279
+ CColor :: Yellow => f. write_str ( "5:11" ) ,
280
+ CColor :: DarkYellow => f. write_str ( "5:3" ) ,
281
+ CColor :: Blue => f. write_str ( "5:12" ) ,
282
+ CColor :: DarkBlue => f. write_str ( "5:4" ) ,
283
+ CColor :: Magenta => f. write_str ( "5:13" ) ,
284
+ CColor :: DarkMagenta => f. write_str ( "5:5" ) ,
285
+ CColor :: Cyan => f. write_str ( "5:14" ) ,
286
+ CColor :: DarkCyan => f. write_str ( "5:6" ) ,
287
+ CColor :: White => f. write_str ( "5:15" ) ,
288
+ CColor :: Grey => f. write_str ( "5:7" ) ,
289
+ CColor :: Rgb { r, g, b } => write ! ( f, "2::{}:{}:{}" , r, g, b) ,
290
+ CColor :: AnsiValue ( val) => write ! ( f, "5:{}" , val) ,
291
+ _ => Ok ( ( ) ) ,
292
+ } ;
293
+ res?;
294
+ write ! ( f, "m" ) ?;
295
+ Ok ( ( ) )
296
+ }
297
+
298
+ #[ cfg( windows) ]
299
+ fn execute_winapi ( & self ) -> crossterm:: Result < ( ) > {
300
+ Err ( std:: io:: Error :: new (
301
+ std:: io:: ErrorKind :: Other ,
302
+ "SetUnderlineColor not supported by winapi." ,
303
+ ) )
304
+ }
305
+ }
0 commit comments