@@ -35,10 +35,10 @@ impl GutterType {
35
35
}
36
36
}
37
37
38
- pub fn width ( self , _view : & View , doc : & Document ) -> usize {
38
+ pub fn width ( self , view : & View , doc : & Document ) -> usize {
39
39
match self {
40
40
GutterType :: Diagnostics => 1 ,
41
- GutterType :: LineNumbers => line_numbers_width ( _view , doc) ,
41
+ GutterType :: LineNumbers => line_numbers_width ( view , doc) ,
42
42
GutterType :: Spacer => 1 ,
43
43
GutterType :: Diff => 1 ,
44
44
}
@@ -140,12 +140,13 @@ pub fn line_numbers<'doc>(
140
140
is_focused : bool ,
141
141
) -> GutterFn < ' doc > {
142
142
let text = doc. text ( ) . slice ( ..) ;
143
- let last_line = view. last_line ( doc) ;
144
- let width = GutterType :: LineNumbers . width ( view, doc) ;
143
+ let width = line_numbers_width ( view, doc) ;
144
+
145
+ let last_line_in_view = view. last_line ( doc) ;
145
146
146
147
// Whether to draw the line number for the last line of the
147
148
// document or not. We only draw it if it's not an empty line.
148
- let draw_last = text. line_to_byte ( last_line ) < text. len_bytes ( ) ;
149
+ let draw_last = text. line_to_byte ( last_line_in_view ) < text. len_bytes ( ) ;
149
150
150
151
let linenr = theme. get ( "ui.linenr" ) ;
151
152
let linenr_select = theme. get ( "ui.linenr.selected" ) ;
@@ -158,7 +159,7 @@ pub fn line_numbers<'doc>(
158
159
let mode = editor. mode ;
159
160
160
161
Box :: new ( move |line : usize , selected : bool , out : & mut String | {
161
- if line == last_line && !draw_last {
162
+ if line == last_line_in_view && !draw_last {
162
163
write ! ( out, "{:>1$}" , '~' , width) . unwrap ( ) ;
163
164
Some ( linenr)
164
165
} else {
@@ -187,14 +188,19 @@ pub fn line_numbers<'doc>(
187
188
} )
188
189
}
189
190
190
- pub fn line_numbers_width ( _view : & View , doc : & Document ) -> usize {
191
+ /// The width of a "line-numbers" gutter
192
+ ///
193
+ /// The width of the gutter depends on the number of lines in the document,
194
+ /// whether there is content on the last line (the `~` line), and the
195
+ /// `editor.gutters.line-numbers.min-width` settings.
196
+ fn line_numbers_width ( view : & View , doc : & Document ) -> usize {
191
197
let text = doc. text ( ) ;
192
198
let last_line = text. len_lines ( ) . saturating_sub ( 1 ) ;
193
199
let draw_last = text. line_to_byte ( last_line) < text. len_bytes ( ) ;
194
200
let last_drawn = if draw_last { last_line + 1 } else { last_line } ;
195
-
196
- // set a lower bound to 2-chars to minimize ambiguous relative line numbers
197
- std :: cmp :: max ( count_digits ( last_drawn ) , 2 )
201
+ let digits = count_digits ( last_drawn ) ;
202
+ let n_min = view . gutters . line_numbers . min_width ;
203
+ digits . max ( n_min )
198
204
}
199
205
200
206
pub fn padding < ' doc > (
@@ -282,3 +288,82 @@ pub fn diagnostics_or_breakpoints<'doc>(
282
288
breakpoints ( line, selected, out) . or_else ( || diagnostics ( line, selected, out) )
283
289
} )
284
290
}
291
+
292
+ #[ cfg( test) ]
293
+ mod tests {
294
+ use super :: * ;
295
+ use crate :: document:: Document ;
296
+ use crate :: editor:: { GutterConfig , GutterLineNumbersConfig } ;
297
+ use crate :: graphics:: Rect ;
298
+ use crate :: DocumentId ;
299
+ use helix_core:: Rope ;
300
+
301
+ #[ test]
302
+ fn test_default_gutter_widths ( ) {
303
+ let mut view = View :: new ( DocumentId :: default ( ) , GutterConfig :: default ( ) ) ;
304
+ view. area = Rect :: new ( 40 , 40 , 40 , 40 ) ;
305
+
306
+ let rope = Rope :: from_str ( "abc\n \t def" ) ;
307
+ let doc = Document :: from ( rope, None ) ;
308
+
309
+ assert_eq ! ( view. gutters. layout. len( ) , 5 ) ;
310
+ assert_eq ! ( view. gutters. layout[ 0 ] . width( & view, & doc) , 1 ) ;
311
+ assert_eq ! ( view. gutters. layout[ 1 ] . width( & view, & doc) , 1 ) ;
312
+ assert_eq ! ( view. gutters. layout[ 2 ] . width( & view, & doc) , 3 ) ;
313
+ assert_eq ! ( view. gutters. layout[ 3 ] . width( & view, & doc) , 1 ) ;
314
+ assert_eq ! ( view. gutters. layout[ 4 ] . width( & view, & doc) , 1 ) ;
315
+ }
316
+
317
+ #[ test]
318
+ fn test_configured_gutter_widths ( ) {
319
+ let gutters = GutterConfig {
320
+ layout : vec ! [ GutterType :: Diagnostics ] ,
321
+ ..Default :: default ( )
322
+ } ;
323
+
324
+ let mut view = View :: new ( DocumentId :: default ( ) , gutters) ;
325
+ view. area = Rect :: new ( 40 , 40 , 40 , 40 ) ;
326
+
327
+ let rope = Rope :: from_str ( "abc\n \t def" ) ;
328
+ let doc = Document :: from ( rope, None ) ;
329
+
330
+ assert_eq ! ( view. gutters. layout. len( ) , 1 ) ;
331
+ assert_eq ! ( view. gutters. layout[ 0 ] . width( & view, & doc) , 1 ) ;
332
+
333
+ let gutters = GutterConfig {
334
+ layout : vec ! [ GutterType :: Diagnostics , GutterType :: LineNumbers ] ,
335
+ line_numbers : GutterLineNumbersConfig { min_width : 10 } ,
336
+ } ;
337
+
338
+ let mut view = View :: new ( DocumentId :: default ( ) , gutters) ;
339
+ view. area = Rect :: new ( 40 , 40 , 40 , 40 ) ;
340
+
341
+ let rope = Rope :: from_str ( "abc\n \t def" ) ;
342
+ let doc = Document :: from ( rope, None ) ;
343
+
344
+ assert_eq ! ( view. gutters. layout. len( ) , 2 ) ;
345
+ assert_eq ! ( view. gutters. layout[ 0 ] . width( & view, & doc) , 1 ) ;
346
+ assert_eq ! ( view. gutters. layout[ 1 ] . width( & view, & doc) , 10 ) ;
347
+ }
348
+
349
+ #[ test]
350
+ fn test_line_numbers_gutter_width_resizes ( ) {
351
+ let gutters = GutterConfig {
352
+ layout : vec ! [ GutterType :: Diagnostics , GutterType :: LineNumbers ] ,
353
+ line_numbers : GutterLineNumbersConfig { min_width : 1 } ,
354
+ } ;
355
+
356
+ let mut view = View :: new ( DocumentId :: default ( ) , gutters) ;
357
+ view. area = Rect :: new ( 40 , 40 , 40 , 40 ) ;
358
+
359
+ let rope = Rope :: from_str ( "a\n b" ) ;
360
+ let doc_short = Document :: from ( rope, None ) ;
361
+
362
+ let rope = Rope :: from_str ( "a\n b\n c\n d\n e\n f\n g\n h\n i\n j\n k\n l\n m\n n\n o\n p" ) ;
363
+ let doc_long = Document :: from ( rope, None ) ;
364
+
365
+ assert_eq ! ( view. gutters. layout. len( ) , 2 ) ;
366
+ assert_eq ! ( view. gutters. layout[ 1 ] . width( & view, & doc_short) , 1 ) ;
367
+ assert_eq ! ( view. gutters. layout[ 1 ] . width( & view, & doc_long) , 2 ) ;
368
+ }
369
+ }
0 commit comments