Coverage Report

Created: 2024-07-06 06:44

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustyline-11.0.0/src/config.rs
Line
Count
Source (jump to first uncovered line)
1
//! Customize line editor
2
use crate::Result;
3
use std::default::Default;
4
5
/// User preferences
6
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7
pub struct Config {
8
    /// Maximum number of entries in History.
9
    max_history_size: usize, // history_max_entries
10
    history_duplicates: HistoryDuplicates,
11
    history_ignore_space: bool,
12
    completion_type: CompletionType,
13
    /// When listing completion alternatives, only display
14
    /// one screen of possibilities at a time.
15
    completion_prompt_limit: usize,
16
    /// Duration (milliseconds) Rustyline will wait for a character when
17
    /// reading an ambiguous key sequence.
18
    keyseq_timeout: i32,
19
    /// Emacs or Vi mode
20
    edit_mode: EditMode,
21
    /// If true, each nonblank line returned by `readline` will be
22
    /// automatically added to the history.
23
    auto_add_history: bool,
24
    /// Beep or Flash or nothing
25
    bell_style: BellStyle,
26
    /// if colors should be enabled.
27
    color_mode: ColorMode,
28
    /// Whether to use stdio or not
29
    behavior: Behavior,
30
    /// Horizontal space taken by a tab.
31
    tab_stop: usize,
32
    /// Indentation size for indent/dedent commands
33
    indent_size: usize,
34
    /// Check if cursor position is at leftmost before displaying prompt
35
    check_cursor_position: bool,
36
    /// Bracketed paste on unix platform
37
    enable_bracketed_paste: bool,
38
}
39
40
impl Config {
41
    /// Returns a `Config` builder.
42
    #[must_use]
43
0
    pub fn builder() -> Builder {
44
0
        Builder::new()
45
0
    }
46
47
    /// Tell the maximum length (i.e. number of entries) for the history.
48
    #[must_use]
49
0
    pub fn max_history_size(&self) -> usize {
50
0
        self.max_history_size
51
0
    }
52
53
0
    pub(crate) fn set_max_history_size(&mut self, max_size: usize) {
54
0
        self.max_history_size = max_size;
55
0
    }
56
57
    /// Tell if lines which match the previous history entry are saved or not
58
    /// in the history list.
59
    ///
60
    /// By default, they are ignored.
61
    #[must_use]
62
0
    pub fn history_duplicates(&self) -> HistoryDuplicates {
63
0
        self.history_duplicates
64
0
    }
65
66
0
    pub(crate) fn set_history_ignore_dups(&mut self, yes: bool) {
67
0
        self.history_duplicates = if yes {
68
0
            HistoryDuplicates::IgnoreConsecutive
69
        } else {
70
0
            HistoryDuplicates::AlwaysAdd
71
        };
72
0
    }
73
74
    /// Tell if lines which begin with a space character are saved or not in
75
    /// the history list.
76
    ///
77
    /// By default, they are saved.
78
    #[must_use]
79
0
    pub fn history_ignore_space(&self) -> bool {
80
0
        self.history_ignore_space
81
0
    }
82
83
0
    pub(crate) fn set_history_ignore_space(&mut self, yes: bool) {
84
0
        self.history_ignore_space = yes;
85
0
    }
86
87
    /// Completion behaviour.
88
    ///
89
    /// By default, `CompletionType::Circular`.
90
    #[must_use]
91
0
    pub fn completion_type(&self) -> CompletionType {
92
0
        self.completion_type
93
0
    }
94
95
    /// When listing completion alternatives, only display
96
    /// one screen of possibilities at a time (used for `CompletionType::List`
97
    /// mode).
98
    #[must_use]
99
0
    pub fn completion_prompt_limit(&self) -> usize {
100
0
        self.completion_prompt_limit
101
0
    }
102
103
    /// Duration (milliseconds) Rustyline will wait for a character when
104
    /// reading an ambiguous key sequence (used for `EditMode::Vi` mode on unix
105
    /// platform).
106
    ///
107
    /// By default, no timeout (-1) or 500ms if `EditMode::Vi` is activated.
108
    #[must_use]
109
0
    pub fn keyseq_timeout(&self) -> i32 {
110
0
        self.keyseq_timeout
111
0
    }
112
113
    /// Emacs or Vi mode
114
    #[must_use]
115
0
    pub fn edit_mode(&self) -> EditMode {
116
0
        self.edit_mode
117
0
    }
118
119
    /// Tell if lines are automatically added to the history.
120
    ///
121
    /// By default, they are not.
122
    #[must_use]
123
0
    pub fn auto_add_history(&self) -> bool {
124
0
        self.auto_add_history
125
0
    }
126
127
    /// Bell style: beep, flash or nothing.
128
    #[must_use]
129
0
    pub fn bell_style(&self) -> BellStyle {
130
0
        self.bell_style
131
0
    }
132
133
    /// Tell if colors should be enabled.
134
    ///
135
    /// By default, they are except if stdout is not a TTY.
136
    #[must_use]
137
0
    pub fn color_mode(&self) -> ColorMode {
138
0
        self.color_mode
139
0
    }
140
141
0
    pub(crate) fn set_color_mode(&mut self, color_mode: ColorMode) {
142
0
        self.color_mode = color_mode;
143
0
    }
144
145
    /// Whether to use stdio or not
146
    ///
147
    /// By default, stdio is used.
148
    #[must_use]
149
0
    pub fn behavior(&self) -> Behavior {
150
0
        self.behavior
151
0
    }
152
153
0
    pub(crate) fn set_behavior(&mut self, behavior: Behavior) {
154
0
        self.behavior = behavior;
155
0
    }
156
157
    /// Horizontal space taken by a tab.
158
    ///
159
    /// By default, 8.
160
    #[must_use]
161
0
    pub fn tab_stop(&self) -> usize {
162
0
        self.tab_stop
163
0
    }
164
165
0
    pub(crate) fn set_tab_stop(&mut self, tab_stop: usize) {
166
0
        self.tab_stop = tab_stop;
167
0
    }
168
169
    /// Check if cursor position is at leftmost before displaying prompt.
170
    ///
171
    /// By default, we don't check.
172
    #[must_use]
173
0
    pub fn check_cursor_position(&self) -> bool {
174
0
        self.check_cursor_position
175
0
    }
176
177
    /// Indentation size used by indentation commands
178
    ///
179
    /// By default, 2.
180
    #[must_use]
181
0
    pub fn indent_size(&self) -> usize {
182
0
        self.indent_size
183
0
    }
184
185
0
    pub(crate) fn set_indent_size(&mut self, indent_size: usize) {
186
0
        self.indent_size = indent_size;
187
0
    }
188
189
    /// Bracketed paste on unix platform
190
    ///
191
    /// By default, it's enabled.
192
    #[must_use]
193
0
    pub fn enable_bracketed_paste(&self) -> bool {
194
0
        self.enable_bracketed_paste
195
0
    }
196
}
197
198
impl Default for Config {
199
0
    fn default() -> Self {
200
0
        Self {
201
0
            max_history_size: 100,
202
0
            history_duplicates: HistoryDuplicates::IgnoreConsecutive,
203
0
            history_ignore_space: false,
204
0
            completion_type: CompletionType::Circular, // TODO Validate
205
0
            completion_prompt_limit: 100,
206
0
            keyseq_timeout: -1,
207
0
            edit_mode: EditMode::Emacs,
208
0
            auto_add_history: false,
209
0
            bell_style: BellStyle::default(),
210
0
            color_mode: ColorMode::Enabled,
211
0
            behavior: Behavior::default(),
212
0
            tab_stop: 8,
213
0
            indent_size: 2,
214
0
            check_cursor_position: false,
215
0
            enable_bracketed_paste: true,
216
0
        }
217
0
    }
218
}
219
220
/// Beep or flash or nothing
221
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
222
pub enum BellStyle {
223
    /// Beep
224
    Audible,
225
    /// Silent
226
    None,
227
    /// Flash screen (not supported)
228
    Visible,
229
}
230
231
/// `Audible` by default on unix (overridden by current Terminal settings).
232
/// `None` on windows.
233
impl Default for BellStyle {
234
    #[cfg(any(windows, target_arch = "wasm32"))]
235
    fn default() -> Self {
236
        BellStyle::None
237
    }
238
239
    #[cfg(unix)]
240
0
    fn default() -> Self {
241
0
        BellStyle::Audible
242
0
    }
243
}
244
245
/// History filter
246
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
247
pub enum HistoryDuplicates {
248
    /// No filter
249
    AlwaysAdd,
250
    /// a line will not be added to the history if it matches the previous entry
251
    IgnoreConsecutive,
252
}
253
254
/// Tab completion style
255
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
256
#[non_exhaustive]
257
pub enum CompletionType {
258
    /// Complete the next full match (like in Vim by default)
259
    Circular,
260
    /// Complete till longest match.
261
    /// When more than one match, list all matches
262
    /// (like in Bash/Readline).
263
    List,
264
265
    /// Complete the match using fuzzy search and selection
266
    /// (like fzf and plugins)
267
    /// Currently only available for unix platforms as dependency on
268
    /// skim->tuikit Compile with `--features=fuzzy` to enable
269
    #[cfg(all(unix, feature = "with-fuzzy"))]
270
    Fuzzy,
271
}
272
273
/// Style of editing / Standard keymaps
274
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
275
#[non_exhaustive]
276
pub enum EditMode {
277
    /// Emacs keymap
278
    Emacs,
279
    /// Vi keymap
280
    Vi,
281
}
282
283
/// Colorization mode
284
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
285
#[non_exhaustive]
286
pub enum ColorMode {
287
    /// Activate highlighting if platform/terminal is supported.
288
    Enabled,
289
    /// Activate highlighting even if platform is not supported (windows < 10).
290
    Forced,
291
    /// Deactivate highlighting even if platform/terminal is supported.
292
    Disabled,
293
}
294
295
/// Should the editor use stdio
296
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
297
#[non_exhaustive]
298
pub enum Behavior {
299
    /// Use stdin / stdout
300
    #[default]
301
    Stdio,
302
    /// Use terminal-style interaction whenever possible, even if 'stdin' and/or
303
    /// 'stdout' are not terminals.
304
    PreferTerm,
305
    // TODO
306
    // Use file-style interaction, reading input from the given file.
307
    // useFile
308
}
309
310
/// Configuration builder
311
#[derive(Clone, Debug, Default)]
312
pub struct Builder {
313
    p: Config,
314
}
315
316
impl Builder {
317
    /// Returns a `Config` builder.
318
    #[must_use]
319
0
    pub fn new() -> Self {
320
0
        Self {
321
0
            p: Config::default(),
322
0
        }
323
0
    }
324
325
    /// Set the maximum length for the history.
326
0
    pub fn max_history_size(mut self, max_size: usize) -> Result<Self> {
327
0
        self.set_max_history_size(max_size)?;
328
0
        Ok(self)
329
0
    }
330
331
    /// Tell if lines which match the previous history entry are saved or not
332
    /// in the history list.
333
    ///
334
    /// By default, they are ignored.
335
0
    pub fn history_ignore_dups(mut self, yes: bool) -> Result<Self> {
336
0
        self.set_history_ignore_dups(yes)?;
337
0
        Ok(self)
338
0
    }
339
340
    /// Tell if lines which begin with a space character are saved or not in
341
    /// the history list.
342
    ///
343
    /// By default, they are saved.
344
    #[must_use]
345
0
    pub fn history_ignore_space(mut self, yes: bool) -> Self {
346
0
        self.set_history_ignore_space(yes);
347
0
        self
348
0
    }
349
350
    /// Set `completion_type`.
351
    #[must_use]
352
0
    pub fn completion_type(mut self, completion_type: CompletionType) -> Self {
353
0
        self.set_completion_type(completion_type);
354
0
        self
355
0
    }
356
357
    /// The number of possible completions that determines when the user is
358
    /// asked whether the list of possibilities should be displayed.
359
    #[must_use]
360
0
    pub fn completion_prompt_limit(mut self, completion_prompt_limit: usize) -> Self {
361
0
        self.set_completion_prompt_limit(completion_prompt_limit);
362
0
        self
363
0
    }
364
365
    /// Timeout for ambiguous key sequences in milliseconds.
366
    /// Currently, it is used only to distinguish a single ESC from an ESC
367
    /// sequence.
368
    /// After seeing an ESC key, wait at most `keyseq_timeout_ms` for another
369
    /// byte.
370
    #[must_use]
371
0
    pub fn keyseq_timeout(mut self, keyseq_timeout_ms: i32) -> Self {
372
0
        self.set_keyseq_timeout(keyseq_timeout_ms);
373
0
        self
374
0
    }
375
376
    /// Choose between Emacs or Vi mode.
377
    #[must_use]
378
0
    pub fn edit_mode(mut self, edit_mode: EditMode) -> Self {
379
0
        self.set_edit_mode(edit_mode);
380
0
        self
381
0
    }
382
383
    /// Tell if lines are automatically added to the history.
384
    ///
385
    /// By default, they are not.
386
    #[must_use]
387
0
    pub fn auto_add_history(mut self, yes: bool) -> Self {
388
0
        self.set_auto_add_history(yes);
389
0
        self
390
0
    }
391
392
    /// Set bell style: beep, flash or nothing.
393
    #[must_use]
394
0
    pub fn bell_style(mut self, bell_style: BellStyle) -> Self {
395
0
        self.set_bell_style(bell_style);
396
0
        self
397
0
    }
398
399
    /// Forces colorization on or off.
400
    ///
401
    /// By default, colorization is on except if stdout is not a TTY.
402
    #[must_use]
403
0
    pub fn color_mode(mut self, color_mode: ColorMode) -> Self {
404
0
        self.set_color_mode(color_mode);
405
0
        self
406
0
    }
407
408
    /// Whether to use stdio or not
409
    ///
410
    /// By default, stdio is used.
411
    #[must_use]
412
0
    pub fn behavior(mut self, behavior: Behavior) -> Self {
413
0
        self.set_behavior(behavior);
414
0
        self
415
0
    }
416
417
    /// Horizontal space taken by a tab.
418
    ///
419
    /// By default, `8`
420
    #[must_use]
421
0
    pub fn tab_stop(mut self, tab_stop: usize) -> Self {
422
0
        self.set_tab_stop(tab_stop);
423
0
        self
424
0
    }
425
426
    /// Check if cursor position is at leftmost before displaying prompt.
427
    ///
428
    /// By default, we don't check.
429
    #[must_use]
430
0
    pub fn check_cursor_position(mut self, yes: bool) -> Self {
431
0
        self.set_check_cursor_position(yes);
432
0
        self
433
0
    }
434
435
    /// Indentation size
436
    ///
437
    /// By default, `2`
438
    #[must_use]
439
0
    pub fn indent_size(mut self, indent_size: usize) -> Self {
440
0
        self.set_indent_size(indent_size);
441
0
        self
442
0
    }
443
444
    /// Enable or disable bracketed paste on unix platform
445
    ///
446
    /// By default, it's enabled.
447
    #[must_use]
448
0
    pub fn bracketed_paste(mut self, enabled: bool) -> Self {
449
0
        self.enable_bracketed_paste(enabled);
450
0
        self
451
0
    }
452
453
    /// Builds a `Config` with the settings specified so far.
454
    #[must_use]
455
0
    pub fn build(self) -> Config {
456
0
        self.p
457
0
    }
458
}
459
460
impl Configurer for Builder {
461
0
    fn config_mut(&mut self) -> &mut Config {
462
0
        &mut self.p
463
0
    }
464
}
465
466
/// Trait for component that holds a `Config`.
467
pub trait Configurer {
468
    /// `Config` accessor.
469
    fn config_mut(&mut self) -> &mut Config;
470
471
    /// Set the maximum length for the history.
472
0
    fn set_max_history_size(&mut self, max_size: usize) -> Result<()> {
473
0
        self.config_mut().set_max_history_size(max_size);
474
0
        Ok(())
475
0
    }
476
477
    /// Tell if lines which match the previous history entry are saved or not
478
    /// in the history list.
479
    ///
480
    /// By default, they are ignored.
481
0
    fn set_history_ignore_dups(&mut self, yes: bool) -> Result<()> {
482
0
        self.config_mut().set_history_ignore_dups(yes);
483
0
        Ok(())
484
0
    }
485
486
    /// Tell if lines which begin with a space character are saved or not in
487
    /// the history list.
488
    ///
489
    /// By default, they are saved.
490
0
    fn set_history_ignore_space(&mut self, yes: bool) {
491
0
        self.config_mut().set_history_ignore_space(yes);
492
0
    }
493
    /// Set `completion_type`.
494
0
    fn set_completion_type(&mut self, completion_type: CompletionType) {
495
0
        self.config_mut().completion_type = completion_type;
496
0
    }
497
498
    /// The number of possible completions that determines when the user is
499
    /// asked whether the list of possibilities should be displayed.
500
0
    fn set_completion_prompt_limit(&mut self, completion_prompt_limit: usize) {
501
0
        self.config_mut().completion_prompt_limit = completion_prompt_limit;
502
0
    }
503
504
    /// Timeout for ambiguous key sequences in milliseconds.
505
0
    fn set_keyseq_timeout(&mut self, keyseq_timeout_ms: i32) {
506
0
        self.config_mut().keyseq_timeout = keyseq_timeout_ms;
507
0
    }
508
509
    /// Choose between Emacs or Vi mode.
510
0
    fn set_edit_mode(&mut self, edit_mode: EditMode) {
511
0
        self.config_mut().edit_mode = edit_mode;
512
0
        match edit_mode {
513
0
            EditMode::Emacs => self.set_keyseq_timeout(-1), // no timeout
514
0
            EditMode::Vi => self.set_keyseq_timeout(500),
515
        }
516
0
    }
517
518
    /// Tell if lines are automatically added to the history.
519
    ///
520
    /// By default, they are not.
521
0
    fn set_auto_add_history(&mut self, yes: bool) {
522
0
        self.config_mut().auto_add_history = yes;
523
0
    }
524
525
    /// Set bell style: beep, flash or nothing.
526
0
    fn set_bell_style(&mut self, bell_style: BellStyle) {
527
0
        self.config_mut().bell_style = bell_style;
528
0
    }
529
530
    /// Forces colorization on or off.
531
    ///
532
    /// By default, colorization is on except if stdout is not a TTY.
533
0
    fn set_color_mode(&mut self, color_mode: ColorMode) {
534
0
        self.config_mut().set_color_mode(color_mode);
535
0
    }
536
537
    /// Whether to use stdio or not
538
    ///
539
    /// By default, stdio is used.
540
0
    fn set_behavior(&mut self, behavior: Behavior) {
541
0
        self.config_mut().set_behavior(behavior);
542
0
    }
543
544
    /// Horizontal space taken by a tab.
545
    ///
546
    /// By default, `8`
547
0
    fn set_tab_stop(&mut self, tab_stop: usize) {
548
0
        self.config_mut().set_tab_stop(tab_stop);
549
0
    }
550
551
    /// Check if cursor position is at leftmost before displaying prompt.
552
    ///
553
    /// By default, we don't check.
554
0
    fn set_check_cursor_position(&mut self, yes: bool) {
555
0
        self.config_mut().check_cursor_position = yes;
556
0
    }
557
    /// Indentation size for indent/dedent commands
558
    ///
559
    /// By default, `2`
560
0
    fn set_indent_size(&mut self, size: usize) {
561
0
        self.config_mut().set_indent_size(size);
562
0
    }
563
564
    /// Enable or disable bracketed paste on unix platform
565
    ///
566
    /// By default, it's enabled.
567
0
    fn enable_bracketed_paste(&mut self, enabled: bool) {
568
0
        self.config_mut().enable_bracketed_paste = enabled;
569
0
    }
570
}