mirror of
https://github.com/NotAShelf/stash.git
synced 2026-06-09 22:59:57 +00:00
various: fix TUI navigation performance; unicode rendering
Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: I027f00979bd5f354e3ea0257e4b8d8bf6a6a6964
This commit is contained in:
parent
1e54569c59
commit
5d6abab1de
2 changed files with 38 additions and 35 deletions
|
|
@ -168,7 +168,6 @@ impl TuiState {
|
||||||
} else {
|
} else {
|
||||||
self.cursor + 1
|
self.cursor + 1
|
||||||
};
|
};
|
||||||
self.dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Move the cursor up by one, wrapping to `total - 1` at the top.
|
/// Move the cursor up by one, wrapping to `total - 1` at the top.
|
||||||
|
|
@ -181,7 +180,6 @@ impl TuiState {
|
||||||
} else {
|
} else {
|
||||||
self.cursor - 1
|
self.cursor - 1
|
||||||
};
|
};
|
||||||
self.dirty = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resize the window (e.g. terminal resized). Marks dirty so the
|
/// Resize the window (e.g. terminal resized). Marks dirty so the
|
||||||
|
|
@ -515,30 +513,43 @@ impl SqliteClipboardDb {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(i, entry)| {
|
.map(|(i, entry)| {
|
||||||
let mut preview = String::new();
|
let mut preview = String::new();
|
||||||
let mut width = 0;
|
let mut pwidth = 0usize;
|
||||||
for g in entry.1.graphemes(true) {
|
for g in entry.1.graphemes(true) {
|
||||||
let g_width = UnicodeWidthStr::width(g);
|
let gw = UnicodeWidthStr::width(g);
|
||||||
if width + g_width > preview_col {
|
if pwidth + gw > preview_col {
|
||||||
preview.push('…');
|
preview.push('…');
|
||||||
|
pwidth += 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
preview.push_str(g);
|
preview.push_str(g);
|
||||||
width += g_width;
|
pwidth += gw;
|
||||||
}
|
}
|
||||||
let mut mime = String::new();
|
let preview_pad = preview_col.saturating_sub(pwidth);
|
||||||
let mut mwidth = 0;
|
for _ in 0..preview_pad {
|
||||||
for g in entry.2.graphemes(true) {
|
preview.push(' ');
|
||||||
let g_width = UnicodeWidthStr::width(g);
|
|
||||||
if mwidth + g_width > mime_col {
|
|
||||||
mime.push('…');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mime.push_str(g);
|
|
||||||
mwidth += g_width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut mime_trunc = String::new();
|
||||||
|
let mut mwidth = 0usize;
|
||||||
|
for g in entry.2.graphemes(true) {
|
||||||
|
let gw = UnicodeWidthStr::width(g);
|
||||||
|
if mwidth + gw > mime_col {
|
||||||
|
mime_trunc.push('…');
|
||||||
|
mwidth += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mime_trunc.push_str(g);
|
||||||
|
mwidth += gw;
|
||||||
|
}
|
||||||
|
let mime_pad = mime_col.saturating_sub(mwidth);
|
||||||
|
let mime_padded = if mime_pad > 0 {
|
||||||
|
format!("{}{mime_trunc}", " ".repeat(mime_pad))
|
||||||
|
} else {
|
||||||
|
mime_trunc
|
||||||
|
};
|
||||||
|
|
||||||
|
let id = entry.0;
|
||||||
let mut spans = Vec::new();
|
let mut spans = Vec::new();
|
||||||
let (id, preview, mime) = entry;
|
|
||||||
if Some(i) == selected {
|
if Some(i) == selected {
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
highlight_symbol,
|
highlight_symbol,
|
||||||
|
|
@ -554,23 +565,23 @@ impl SqliteClipboardDb {
|
||||||
));
|
));
|
||||||
spans.push(Span::raw(" "));
|
spans.push(Span::raw(" "));
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
format!("{preview:<preview_col$}"),
|
preview,
|
||||||
Style::default()
|
Style::default()
|
||||||
.fg(Color::Yellow)
|
.fg(Color::Yellow)
|
||||||
.add_modifier(Modifier::BOLD),
|
.add_modifier(Modifier::BOLD),
|
||||||
));
|
));
|
||||||
spans.push(Span::raw(" "));
|
spans.push(Span::raw(" "));
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
format!("{mime:>mime_col$}"),
|
mime_padded,
|
||||||
Style::default().fg(Color::Green),
|
Style::default().fg(Color::Green),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
spans.push(Span::raw(" "));
|
spans.push(Span::raw(" "));
|
||||||
spans.push(Span::raw(format!("{id:>id_col$}")));
|
spans.push(Span::raw(format!("{id:>id_col$}")));
|
||||||
spans.push(Span::raw(" "));
|
spans.push(Span::raw(" "));
|
||||||
spans.push(Span::raw(format!("{preview:<preview_col$}")));
|
spans.push(Span::raw(preview));
|
||||||
spans.push(Span::raw(" "));
|
spans.push(Span::raw(" "));
|
||||||
spans.push(Span::raw(format!("{mime:>mime_col$}")));
|
spans.push(Span::raw(mime_padded));
|
||||||
}
|
}
|
||||||
ListItem::new(Line::from(spans))
|
ListItem::new(Line::from(spans))
|
||||||
})
|
})
|
||||||
|
|
@ -635,15 +646,9 @@ impl SqliteClipboardDb {
|
||||||
if actions.search_backspace {
|
if actions.search_backspace {
|
||||||
let new_query = tui
|
let new_query = tui
|
||||||
.search_query
|
.search_query
|
||||||
.chars()
|
.char_indices()
|
||||||
.next_back()
|
.next_back()
|
||||||
.map(|_| {
|
.map(|(i, _)| tui.search_query[..i].to_string())
|
||||||
tui
|
|
||||||
.search_query
|
|
||||||
.chars()
|
|
||||||
.take(tui.search_query.len() - 1)
|
|
||||||
.collect::<String>()
|
|
||||||
})
|
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
if tui.set_search(new_query) {
|
if tui.set_search(new_query) {
|
||||||
// Search changed, refresh count and reset
|
// Search changed, refresh count and reset
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ use regex::Regex;
|
||||||
use rusqlite::{Connection, OptionalExtension, params};
|
use rusqlite::{Connection, OptionalExtension, params};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
use unicode_width::UnicodeWidthChar;
|
||||||
|
|
||||||
pub const DEFAULT_MAX_ENTRY_SIZE: usize = 5_000_000;
|
pub const DEFAULT_MAX_ENTRY_SIZE: usize = 5_000_000;
|
||||||
|
|
||||||
|
|
@ -1076,19 +1077,16 @@ pub fn preview_entry(data: &[u8], mime: Option<&str>, width: u32) -> String {
|
||||||
return trimmed.to_string();
|
return trimmed.to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only allocate new string if we need to replace whitespace
|
|
||||||
let mut result = String::with_capacity(width as usize + 1);
|
let mut result = String::with_capacity(width as usize + 1);
|
||||||
for (char_count, c) in trimmed.chars().enumerate() {
|
let mut disp = 0usize;
|
||||||
if char_count >= width as usize {
|
for c in trimmed.chars() {
|
||||||
|
let cw = UnicodeWidthChar::width(c).unwrap_or(1);
|
||||||
|
if disp + cw > width as usize {
|
||||||
result.push('…');
|
result.push('…');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
result.push(if c.is_whitespace() { ' ' } else { c });
|
||||||
if c.is_whitespace() {
|
disp += cw;
|
||||||
result.push(' ');
|
|
||||||
} else {
|
|
||||||
result.push(c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue