Don't panic on detect columns with --guess flag (#13752)

# Description
This pr addresses the comment:
https://github.com/nushell/nushell/issues/11791#issuecomment-2308384155

It's caused by if the last row have a very different format to the first
row, the value of `end_char` will exceed the `line_char_boundaries`.
Adding a guard for it should avoid such panic.

# User-Facing Changes
The following code should no longer panic:
```shell
"nu_plugin_highlight = '1.2.2+0.97.1'    # A nushell plugin for syntax highlighting
trace_nu_plugin = '0.3.1'               # A wrapper to trace Nu plugins
nu_plugin_bash_env = '0.13.0'           # Nu plugin bash-env
nu_plugin_from_sse = '0.4.0'            # Nushell plugin to convert a HTTP server sent event stream to structured data
... and 90 crates more (use --limit N to see more)" | detect columns -n --guess
```

# Tests + Formatting
Added 1 test.
This commit is contained in:
Wind 2024-09-02 22:29:53 +08:00 committed by GitHub
parent 39bda8986e
commit c150af4279
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -203,7 +203,7 @@ fn split(line: &str, pos: &[usize], trim_space: bool) -> Vec<String> {
if pos[n] <= w {
let end_char = separator_position(&line_chars, p, pos, n);
if start_char > end_char {
if start_char > end_char || end_char >= line_char_boundaries.len() {
break;
}
let col = &line[line_char_boundaries[start_char]..line_char_boundaries[end_char]];
@ -594,6 +594,37 @@ E F G H";
assert_eq!(got, want);
}
#[test]
fn test_guess_no_panic_for_some_cases() {
let input = r#"nu_plugin_highlight = '1.2.2+0.97.1' # A nushell plugin for syntax highlighting
trace_nu_plugin = '0.3.1' # A wrapper to trace Nu plugins
nu_plugin_bash_env = '0.13.0' # Nu plugin bash-env
nu_plugin_from_sse = '0.4.0' # Nushell plugin to convert a HTTP server sent event stream to structured data
... and 90 crates more (use --limit N to see more)"#;
let r = Box::new(std::io::BufReader::new(input.as_bytes())) as Box<dyn std::io::Read>;
let reader = std::io::BufReader::new(r);
let mut guess_width = GuessWidth {
reader,
pos: Vec::new(),
pre_lines: Vec::new(),
pre_count: 0,
limit_split: 0,
};
let first_column_want = [
"nu_plugin_highlight = '1.2.2+0.97.1'",
"trace_nu_plugin = '0.3.1'",
"nu_plugin_bash_env = '0.13.0'",
"nu_plugin_from_sse = '0.4.0'",
"... and 90 crates more (use --limit N",
];
let got = guess_width.read_all();
for (row_indx, row) in got.into_iter().enumerate() {
assert_eq!(row[0], first_column_want[row_indx]);
}
}
#[test]
fn test_to_table() {
let lines = vec![