Make wcwidth an isize

Seems more consistent with the rest of our code.
This commit is contained in:
Johannes Altmanninger 2024-02-14 22:18:49 +01:00
parent 8545b5debe
commit a1ed63fd83
8 changed files with 20 additions and 22 deletions

View file

@ -235,7 +235,7 @@ enum Direction {
} }
fn width_without_escapes(ins: &wstr, start_pos: usize) -> usize { fn width_without_escapes(ins: &wstr, start_pos: usize) -> usize {
let mut width: i32 = 0; let mut width: isize = 0;
for c in ins[start_pos..].chars() { for c in ins[start_pos..].chars() {
let w = fish_wcwidth_visible(c); let w = fish_wcwidth_visible(c);
// We assume that this string is on its own line, // We assume that this string is on its own line,

View file

@ -191,7 +191,7 @@ impl<'args> StringSubCommand<'args> for Shorten<'args> {
// This is somewhat easier. // This is somewhat easier.
while max <= ourmax && pos < line.len() { while max <= ourmax && pos < line.len() {
pos += skip_escapes(&line, pos); pos += skip_escapes(&line, pos);
let w = fish_wcwidth_visible(line.char_at(pos)) as isize; let w = fish_wcwidth_visible(line.char_at(pos));
if w <= 0 || max + w as usize + ell_width <= ourmax { if w <= 0 || max + w as usize + ell_width <= ourmax {
// If it still fits, even if it is the last, we add it. // If it still fits, even if it is the last, we add it.
max = max.saturating_add_signed(w); max = max.saturating_add_signed(w);
@ -202,7 +202,7 @@ impl<'args> StringSubCommand<'args> for Shorten<'args> {
let mut pos2 = pos + 1; let mut pos2 = pos + 1;
while pos2 < line.len() { while pos2 < line.len() {
pos2 += skip_escapes(&line, pos2); pos2 += skip_escapes(&line, pos2);
let w = fish_wcwidth_visible(line.char_at(pos2)) as isize; let w = fish_wcwidth_visible(line.char_at(pos2));
max2 = max2.saturating_add_signed(w); max2 = max2.saturating_add_signed(w);
pos2 += 1; pos2 += 1;
} }

View file

@ -1542,7 +1542,7 @@ pub fn reformat_for_screen(msg: &wstr, termsize: &Termsize) -> WString {
while pos < msg.len() && ![' ', '\n', '\r', '\t'].contains(&msg.char_at(pos)) { while pos < msg.len() && ![' ', '\n', '\r', '\t'].contains(&msg.char_at(pos)) {
// Check is token is wider than one line. If so we mark it as an overflow and break // Check is token is wider than one line. If so we mark it as an overflow and break
// the token. // the token.
let width = fish_wcwidth(msg.char_at(pos)) as isize; let width = fish_wcwidth(msg.char_at(pos));
if (tok_width + width) > (screen_width - 1) { if (tok_width + width) > (screen_width - 1) {
overflow = true; overflow = true;
break; break;

View file

@ -157,7 +157,7 @@ fn guess_emoji_width(vars: &EnvStack) {
if let Some(width_str) = vars.get(L!("fish_emoji_width")) { if let Some(width_str) = vars.get(L!("fish_emoji_width")) {
// The only valid values are 1 or 2; we default to 1 if it was an invalid int. // The only valid values are 1 or 2; we default to 1 if it was an invalid int.
let new_width = fish_wcstoi(&width_str.as_string()).unwrap_or(1).clamp(1, 2); let new_width = fish_wcstoi(&width_str.as_string()).unwrap_or(1).clamp(1, 2);
FISH_EMOJI_WIDTH.store(new_width, Ordering::Relaxed); FISH_EMOJI_WIDTH.store(isize::try_from(new_width).unwrap(), Ordering::Relaxed);
FLOG!( FLOG!(
term_support, term_support,
"Overriding default fish_emoji_width w/", "Overriding default fish_emoji_width w/",
@ -228,7 +228,8 @@ fn handle_change_ambiguous_width(vars: &EnvStack) {
.unwrap_or(1) .unwrap_or(1)
// Clamp in case of negative values. // Clamp in case of negative values.
.max(0); .max(0);
crate::fallback::FISH_AMBIGUOUS_WIDTH.store(new_width, Ordering::Relaxed); crate::fallback::FISH_AMBIGUOUS_WIDTH
.store(isize::try_from(new_width).unwrap(), Ordering::Relaxed);
} }
fn handle_term_size_change(vars: &EnvStack) { fn handle_term_size_change(vars: &EnvStack) {

View file

@ -7,12 +7,12 @@ use crate::widecharwidth::{WcLookupTable, WcWidth};
use crate::{common::is_console_session, wchar::prelude::*}; use crate::{common::is_console_session, wchar::prelude::*};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::cmp; use std::cmp;
use std::sync::atomic::{AtomicI32, Ordering}; use std::sync::atomic::{AtomicIsize, Ordering};
use std::{ffi::CString, mem, os::fd::RawFd}; use std::{ffi::CString, mem, os::fd::RawFd};
/// Width of ambiguous East Asian characters and, as of TR11, all private-use characters. /// Width of ambiguous East Asian characters and, as of TR11, all private-use characters.
/// 1 is the typical default, but we accept any non-negative override via `$fish_ambiguous_width`. /// 1 is the typical default, but we accept any non-negative override via `$fish_ambiguous_width`.
pub static FISH_AMBIGUOUS_WIDTH: AtomicI32 = AtomicI32::new(1); pub static FISH_AMBIGUOUS_WIDTH: AtomicIsize = AtomicIsize::new(1);
/// Width of emoji characters. /// Width of emoji characters.
/// ///
@ -24,23 +24,24 @@ pub static FISH_AMBIGUOUS_WIDTH: AtomicI32 = AtomicI32::new(1);
/// Valid values are 1, and 2. 1 is the typical emoji width used in Unicode 8 while some newer /// Valid values are 1, and 2. 1 is the typical emoji width used in Unicode 8 while some newer
/// terminals use a width of 2 since Unicode 9. /// terminals use a width of 2 since Unicode 9.
// For some reason, this is declared here and exposed here, but is set in `env_dispatch`. // For some reason, this is declared here and exposed here, but is set in `env_dispatch`.
pub static FISH_EMOJI_WIDTH: AtomicI32 = AtomicI32::new(1); pub static FISH_EMOJI_WIDTH: AtomicIsize = AtomicIsize::new(1);
static WC_LOOKUP_TABLE: Lazy<WcLookupTable> = Lazy::new(WcLookupTable::new); static WC_LOOKUP_TABLE: Lazy<WcLookupTable> = Lazy::new(WcLookupTable::new);
/// A safe wrapper around the system `wcwidth()` function /// A safe wrapper around the system `wcwidth()` function
pub fn wcwidth(c: char) -> i32 { pub fn wcwidth(c: char) -> isize {
extern "C" { extern "C" {
pub fn wcwidth(c: libc::wchar_t) -> libc::c_int; pub fn wcwidth(c: libc::wchar_t) -> libc::c_int;
} }
const _: () = assert!(mem::size_of::<libc::wchar_t>() >= mem::size_of::<char>()); const _: () = assert!(mem::size_of::<libc::wchar_t>() >= mem::size_of::<char>());
unsafe { wcwidth(c as libc::wchar_t) } let width = unsafe { wcwidth(c as libc::wchar_t) };
isize::try_from(width).unwrap()
} }
// Big hack to use our versions of wcswidth where we know them to be broken, which is // Big hack to use our versions of wcswidth where we know them to be broken, which is
// EVERYWHERE (https://github.com/fish-shell/fish-shell/issues/2199) // EVERYWHERE (https://github.com/fish-shell/fish-shell/issues/2199)
pub fn fish_wcwidth(c: char) -> i32 { pub fn fish_wcwidth(c: char) -> isize {
// The system version of wcwidth should accurately reflect the ability to represent characters // The system version of wcwidth should accurately reflect the ability to represent characters
// in the console session, but knows nothing about the capabilities of other terminal emulators // in the console session, but knows nothing about the capabilities of other terminal emulators
// or ttys. Use it from the start only if we are logged in to the physical console. // or ttys. Use it from the start only if we are logged in to the physical console.
@ -84,7 +85,7 @@ pub fn fish_wcwidth(c: char) -> i32 {
/// fish's internal versions of wcwidth and wcswidth, which can use an internal implementation if /// fish's internal versions of wcwidth and wcswidth, which can use an internal implementation if
/// the system one is busted. /// the system one is busted.
pub fn fish_wcswidth(s: &wstr) -> i32 { pub fn fish_wcswidth(s: &wstr) -> isize {
let mut result = 0; let mut result = 0;
for c in s.chars() { for c in s.chars() {
let w = fish_wcwidth(c); let w = fish_wcwidth(c);

View file

@ -99,14 +99,12 @@ impl Line {
/// This follows fish_wcswidth() semantics, except that characters whose width would be -1 are /// This follows fish_wcswidth() semantics, except that characters whose width would be -1 are
/// treated as 0. /// treated as 0.
pub fn wcswidth_min_0(&self, max: usize /* = usize::MAX */) -> usize { pub fn wcswidth_min_0(&self, max: usize /* = usize::MAX */) -> usize {
let mut result = 0; let mut result: usize = 0;
for c in &self.text[..max.min(self.text.len())] { for c in &self.text[..max.min(self.text.len())] {
let w = fish_wcwidth_visible(c.character); let w = fish_wcwidth_visible(c.character);
// A backspace at the start of the line does nothing. // A backspace at the start of the line does nothing.
if w > 0 || result > 0 { if w > 0 || result > 0 {
result = result = result.checked_add_signed(w).unwrap();
usize::try_from(isize::try_from(result).unwrap() + isize::try_from(w).unwrap())
.unwrap();
} }
} }
result result
@ -1530,9 +1528,7 @@ fn measure_run_from(
let w = fish_wcwidth_visible(input.char_at(idx)); let w = fish_wcwidth_visible(input.char_at(idx));
// A backspace at the start of the line does nothing. // A backspace at the start of the line does nothing.
if w != -1 || width > 0 { if w != -1 || width > 0 {
width = width = width.checked_add_signed(w).unwrap();
usize::try_from(isize::try_from(width).unwrap() + isize::try_from(w).unwrap())
.unwrap();
} }
} }
idx += 1; idx += 1;

View file

@ -538,7 +538,7 @@ impl<'a> Iterator for LineIterator<'a> {
} }
/// Like fish_wcwidth, but returns 0 for characters with no real width instead of -1. /// Like fish_wcwidth, but returns 0 for characters with no real width instead of -1.
pub fn fish_wcwidth_visible(c: char) -> i32 { pub fn fish_wcwidth_visible(c: char) -> isize {
if c == '\x08' { if c == '\x08' {
return -1; return -1;
} }

View file

@ -498,7 +498,7 @@ pub fn fish_iswgraph(c: char) -> bool {
!fish_reserved_codepoint(c) && (fish_is_pua(c) || unsafe { iswgraph(c as libc::wchar_t) } != 0) !fish_reserved_codepoint(c) && (fish_is_pua(c) || unsafe { iswgraph(c as libc::wchar_t) } != 0)
} }
pub fn fish_wcswidth(s: &wstr) -> libc::c_int { pub fn fish_wcswidth(s: &wstr) -> isize {
fallback::fish_wcswidth(s) fallback::fish_wcswidth(s)
} }