From 334fb7011e45e12782ae2b7ed2b50deaa58effcf Mon Sep 17 00:00:00 2001 From: extrawurst Date: Tue, 20 Jun 2023 18:04:27 +0200 Subject: [PATCH] fix char_count with utf8 chars (fixes #1726) --- CHANGELOG.md | 3 +++ src/components/textinput.rs | 24 ++++++++++++++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5582aa8283..75e6b3222e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added * support 'n'/'p' key to move to the next/prev hunk in diff component [[@hamflx](https://github.com/hamflx)] ([#1523](https://github.com/extrawurst/gitui/issues/1523)) +### Fixes +* fix commit dialog char count for multibyte characters ([#1726](https://github.com/extrawurst/gitui/issues/1726)) + ## [0.23.0] - 2022-06-19 **reset to commit** diff --git a/src/components/textinput.rs b/src/components/textinput.rs index 1f527b6078..5052a8e0a8 100644 --- a/src/components/textinput.rs +++ b/src/components/textinput.rs @@ -22,6 +22,7 @@ use ratatui::{ Frame, }; use std::{cell::Cell, collections::HashMap, ops::Range}; +use unicode_segmentation::UnicodeSegmentation; #[derive(PartialEq, Eq)] pub enum InputType { @@ -43,6 +44,7 @@ pub struct TextInputComponent { input_type: InputType, current_area: Cell, embed: bool, + char_count: usize, } impl TextInputComponent { @@ -66,6 +68,7 @@ impl TextInputComponent { input_type: InputType::Multiline, current_area: Cell::new(Rect::default()), embed: false, + char_count: 0, } } @@ -80,6 +83,7 @@ impl TextInputComponent { /// Clear the `msg`. pub fn clear(&mut self) { self.msg.clear(); + self.update_count(); self.cursor_position = 0; } @@ -203,6 +207,7 @@ impl TextInputComponent { if self.cursor_position > 0 { self.decr_cursor(); self.msg.remove(self.cursor_position); + self.update_count(); } } @@ -210,6 +215,7 @@ impl TextInputComponent { pub fn set_text(&mut self, msg: String) { self.msg = msg; self.cursor_position = 0; + self.update_count(); } /// Set the `title`. @@ -303,10 +309,12 @@ impl TextInputComponent { } fn draw_char_count(&self, f: &mut Frame, r: Rect) { - let count = self.msg.len(); - if count > 0 { - let w = Paragraph::new(format!("[{count} chars]")) - .alignment(Alignment::Right); + if self.char_count > 0 { + let w = Paragraph::new(format!( + "[{} chars]", + self.char_count + )) + .alignment(Alignment::Right); let mut rect = { let mut rect = r; @@ -323,6 +331,10 @@ impl TextInputComponent { f.render_widget(w, rect); } } + + fn update_count(&mut self) { + self.char_count = self.msg.graphemes(true).count(); + } } // merges last line of `txt` with first of `append` so we do not generate unneeded newlines @@ -432,6 +444,7 @@ impl Component for TextInputComponent { match e.code { KeyCode::Char(c) if !is_ctrl => { self.msg.insert(self.cursor_position, c); + self.update_count(); self.incr_cursor(); return Ok(EventState::Consumed); } @@ -441,6 +454,7 @@ impl Component for TextInputComponent { self.cursor_position..pos, "", ); + self.update_count(); } return Ok(EventState::Consumed); } @@ -455,6 +469,7 @@ impl Component for TextInputComponent { "", ); self.cursor_position = pos; + self.update_count(); } return Ok(EventState::Consumed); } @@ -475,6 +490,7 @@ impl Component for TextInputComponent { KeyCode::Delete => { if self.cursor_position < self.msg.len() { self.msg.remove(self.cursor_position); + self.update_count(); } return Ok(EventState::Consumed); }