mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 17:25:15 +02:00
Fix UTF-8 multibyte handling in explore
inputs (#16325)
# Description `explore` was reading the byte length for computing: - `:` command input cursor positions - `/`/`?` search mode cursor positions - `:try` input box cursor positions - search highlighting Fixed this for the majority of cases by using `unicode_width`, this is only best effort as terminals don't need to follow those expectations but for the most cases (traditional language scripts etc.) this should lead to better result. The only way around the uncertainty would be to perform the highlighting/cursor marking as we go, but this may not be as compatible with the `ratatui` framework. Closes #16312 # User-Facing Changes Fixed cursor position and search highlighting for non-ASCII characters, with the caveat mentioned above. # Tests + Formatting Manually tested
This commit is contained in:
committed by
GitHub
parent
7cc1a86459
commit
d528bb713b
@ -37,6 +37,7 @@ use std::{
|
||||
io::{self, Stdout},
|
||||
result,
|
||||
};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
pub type Frame<'a> = ratatui::Frame<'a>;
|
||||
pub type Terminal = ratatui::Terminal<CrosstermBackend<Stdout>>;
|
||||
@ -450,14 +451,14 @@ fn run_command(
|
||||
fn set_cursor_cmd_bar(f: &mut Frame, area: Rect, pager: &Pager) {
|
||||
if pager.cmd_buf.is_cmd_input {
|
||||
// todo: deal with a situation where we exceed the bar width
|
||||
let next_pos = (pager.cmd_buf.buf_cmd2.len() + 1) as u16;
|
||||
let next_pos = (pager.cmd_buf.buf_cmd2.width() + 1) as u16;
|
||||
// 1 skips a ':' char
|
||||
if next_pos < area.width {
|
||||
f.set_cursor_position((next_pos, area.height - 1));
|
||||
}
|
||||
} else if pager.search_buf.is_search_input {
|
||||
// todo: deal with a situation where we exceed the bar width
|
||||
let next_pos = (pager.search_buf.buf_cmd_input.len() + 1) as u16;
|
||||
let next_pos = (pager.search_buf.buf_cmd_input.width() + 1) as u16;
|
||||
// 1 skips a ':' char
|
||||
if next_pos < area.width {
|
||||
f.set_cursor_position((next_pos, area.height - 1));
|
||||
@ -558,7 +559,8 @@ fn render_cmd_bar_search(f: &mut Frame, area: Rect, pager: &Pager<'_>, config: &
|
||||
|
||||
fn render_cmd_bar_cmd(f: &mut Frame, area: Rect, pager: &Pager, config: &ExploreConfig) {
|
||||
let mut input = pager.cmd_buf.buf_cmd2.as_str();
|
||||
if input.len() > area.width as usize + 1 {
|
||||
// UnicodeWidthStr::width is a best guess
|
||||
if input.width() > area.width as usize + 1 {
|
||||
// in such case we take last max_cmd_len chars
|
||||
let take_bytes = input
|
||||
.chars()
|
||||
@ -591,7 +593,8 @@ fn highlight_search_results(f: &mut Frame, pager: &Pager, layout: &Layout, style
|
||||
if let Some(p) = text.find(&pager.search_buf.buf_cmd_input) {
|
||||
let p = covert_bytes_to_chars(&text, p);
|
||||
|
||||
let w = pager.search_buf.buf_cmd_input.len() as u16;
|
||||
// this width is a best guess
|
||||
let w = pager.search_buf.buf_cmd_input.width() as u16;
|
||||
let area = Rect::new(e.area.x + p as u16, e.area.y, w, 1);
|
||||
|
||||
f.render_widget(highlight_block.clone(), area);
|
||||
|
@ -16,6 +16,7 @@ use ratatui::{
|
||||
widgets::{BorderType, Borders, Paragraph},
|
||||
};
|
||||
use std::cmp::min;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
pub struct TryView {
|
||||
input: Value,
|
||||
@ -87,8 +88,8 @@ impl View for TryView {
|
||||
|
||||
let mut input = self.command.as_str();
|
||||
|
||||
let max_cmd_len = min(input.len() as u16, cmd_input_area.width);
|
||||
if input.len() as u16 > max_cmd_len {
|
||||
let max_cmd_len = min(input.width() as u16, cmd_input_area.width);
|
||||
if input.width() as u16 > max_cmd_len {
|
||||
// in such case we take last max_cmd_len chars
|
||||
let take_bytes = input
|
||||
.chars()
|
||||
|
Reference in New Issue
Block a user