fix clippy

This commit is contained in:
2026-06-04 17:56:31 +07:00
parent ce8f431aaa
commit ef227032bb
4 changed files with 32 additions and 427 deletions

View File

@@ -270,60 +270,19 @@ impl NostrRegistry {
let key_path = self.key_dir.join(format!("{}.npub", npub));
let app_keys = self.app_keys.clone();
if let Ok(payload) = std::fs::read_to_string(key_path) {
if !payload.is_empty() {
cx.background_spawn(async move {
let decrypted = app_keys.nip44_decrypt(&public_key, &payload).await?;
let secret = SecretKey::parse(&decrypted)?;
let keys = Keys::new(secret);
if let Ok(payload) = std::fs::read_to_string(key_path)
&& !payload.is_empty()
{
return cx.background_spawn(async move {
let decrypted = app_keys.nip44_decrypt(&public_key, &payload).await?;
let secret = SecretKey::parse(&decrypted)?;
let keys = Keys::new(secret);
Ok(keys.into_nostr_signer())
})
} else {
self.get_secret_keyring(&npub, cx)
}
} else {
self.get_secret_keyring(&npub, cx)
Ok(keys.into_nostr_signer())
});
}
}
/// Get the secret for a given npub in the OS credentials store.
#[deprecated = "Use get_secret instead"]
fn get_secret_keyring(
&self,
user: &str,
cx: &App,
) -> Task<Result<Arc<dyn NostrSigner>, Error>> {
let read = cx.read_credentials(user);
let app_keys = self.app_keys.clone();
cx.background_spawn(async move {
let (_, secret) = read
.await
.map_err(|_| anyhow!("Failed to get signer. Please re-import the secret key"))?
.ok_or_else(|| anyhow!("Failed to get signer. Please re-import the secret key"))?;
// Try to parse as a direct secret key first
if let Ok(secret_key) = SecretKey::from_slice(&secret) {
return Ok(Keys::new(secret_key).into_nostr_signer());
}
// Convert the secret into string
let sec = String::from_utf8(secret)
.map_err(|_| anyhow!("Failed to parse secret as UTF-8"))?;
// Try to parse as a NIP-46 URI
let uri =
NostrConnectUri::parse(&sec).map_err(|_| anyhow!("Failed to parse NIP-46 URI"))?;
let timeout = Duration::from_secs(NOSTR_CONNECT_TIMEOUT);
let mut nip46 = NostrConnect::new(uri, app_keys, timeout, None)?;
// Set the auth URL handler
nip46.auth_url_handler(CoopAuthUrlHandler);
Ok(nip46.into_nostr_signer())
})
Task::ready(Err(anyhow::anyhow!("No secret found")))
}
/// Add a new npub to the keys directory

View File

@@ -1,12 +1,4 @@
/// Display mapping system for Editor/Input.
///
/// This module implements a layered display mapping architecture:
/// - **WrapMap**: Handles soft-wrapping (buffer → wrap rows)
/// - **FoldMap**: Handles folding (wrap rows → display rows)
/// - **DisplayMap**: Public facade for Editor/Input
///
/// The goal is to provide a clean, unified API where Editor only needs to know
/// about `BufferPoint ↔ DisplayPoint` mapping, without worrying about internal wrap/fold complexity.
#[allow(clippy::module_inception)]
mod display_map;
mod fold_map;
#[cfg(not(target_family = "wasm"))]

View File

@@ -1,8 +1,7 @@
use std::ops::Range;
use gpui::Half;
use gpui::{
App, Font, LineFragment, Pixels, Point, ShapedLine, Size, TextAlign, Window, point, px,
App, Font, Half, LineFragment, Pixels, Point, ShapedLine, Size, TextAlign, Window, point, px,
size,
};
use ropey::Rope;
@@ -97,7 +96,7 @@ impl TextWrapper {
/// Get the line item by row index.
#[inline]
pub(crate) fn line(&self, row: usize) -> Option<&LineItem> {
self.lines.iter().skip(row).next()
self.lines.get(row)
}
pub(crate) fn set_wrap_width(&mut self, wrap_width: Option<Pixels>, cx: &mut App) {
@@ -228,7 +227,7 @@ impl TextWrapper {
});
}
if self.lines.len() == 0 {
if self.lines.is_empty() {
self.lines = new_lines;
} else {
self.lines.splice(rows_range, new_lines);
@@ -246,7 +245,7 @@ impl TextWrapper {
///
/// If the `text` is the same as the current text, do nothing.
fn update_all(&mut self, text: &Rope, cx: &mut App) {
self.update(text, &(0..text.len()), &text, cx);
self.update(text, &(0..text.len()), text, cx);
}
/// Return display point (with soft wrap) from the given byte offset in the text.
@@ -278,7 +277,8 @@ impl TextWrapper {
// Otherwise return the eof of the line.
let last_range = line.wrapped_lines.last().unwrap_or(&(0..0));
let ix = line.lines_len().saturating_sub(1);
return WrapDisplayPoint::new(wrapped_row + ix, ix, last_range.len());
WrapDisplayPoint::new(wrapped_row + ix, ix, last_range.len())
}
/// Return byte offset in the text from the given display point (with soft wrap).
@@ -301,7 +301,7 @@ impl TextWrapper {
wrapped_row += line.lines_len();
}
return self.text.len();
self.text.len()
}
pub(crate) fn display_point_to_point(&self, point: WrapDisplayPoint) -> TreeSitterPoint {
@@ -580,351 +580,3 @@ impl LineLayout {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::rc::Rc;
use gpui::{Boundary, FontFeatures, FontStyle, FontWeight, px};
#[test]
fn test_update() {
let font = gpui::Font {
family: "Arial".into(),
weight: FontWeight::default(),
style: FontStyle::Normal,
features: FontFeatures::default(),
fallbacks: None,
};
let mut wrapper = TextWrapper::new(font, px(14.), None);
let mut text = Rope::from(
"Hello, 世界!\r\nThis is second line.\nThis is third line.\n这里是第 4 行。",
);
fn fake_wrap_line(_line: &str, _wrap_width: Pixels) -> Vec<Boundary> {
vec![]
}
#[track_caller]
fn assert_wrapper_lines(text: &Rope, wrapper: &TextWrapper, expected_lines: &[&[&str]]) {
let mut actual_lines = vec![];
let mut offset = 0;
for line in wrapper.lines.iter() {
actual_lines.push(
line.wrapped_lines
.iter()
.map(|range| text.slice(offset + range.start..offset + range.end))
.collect::<Vec<_>>(),
);
// +1 \n
offset += line.len() + 1;
}
assert_eq!(actual_lines, expected_lines);
}
wrapper._update(&text, &(0..text.len()), &text, &mut fake_wrap_line);
assert_eq!(wrapper.lines.len(), 4);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["Hello, 世界!\r"],
&["This is second line."],
&["This is third line."],
&["这里是第 4 行。"],
],
);
// Add a new text to end
let range = text.len()..text.len();
let new_text = "New text";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &Rope::from(new_text), &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"Hello, 世界!\r\nThis is second line.\nThis is third line.\n这里是第 4 行。New text"
);
assert_eq!(wrapper.lines.len(), 4);
assert_eq!(wrapper.lines.len(), 4);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["Hello, 世界!\r"],
&["This is second line."],
&["This is third line."],
&["这里是第 4 行。New text"],
],
);
// Replace first line `Hello` to `AAA`
let range = 0..5;
let new_text = "AAA";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &Rope::from(new_text), &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"AAA, 世界!\r\nThis is second line.\nThis is third line.\n这里是第 4 行。New text"
);
assert_eq!(wrapper.lines.len(), 4);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["AAA, 世界!\r"],
&["This is second line."],
&["This is third line."],
&["这里是第 4 行。New text"],
],
);
// Remove the second line
let start_offset = text.line_start_offset(1);
let end_offset = text.line_end_offset(1);
let range = start_offset..end_offset + 1;
text.replace(range.clone(), "");
wrapper._update(&text, &range, &Rope::from(""), &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"AAA, 世界!\r\nThis is third line.\n这里是第 4 行。New text"
);
assert_eq!(wrapper.lines.len(), 3);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["AAA, 世界!\r"],
&["This is third line."],
&["这里是第 4 行。New text"],
],
);
// Replace the first 2 lines to "This is a new line."
let range = text.line_start_offset(0)..text.line_end_offset(1) + 1;
let new_text = "This is a new line.\nThis is new line 2.\n";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &Rope::from(new_text), &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"This is a new line.\nThis is new line 2.\n这里是第 4 行。New text"
);
assert_eq!(wrapper.lines.len(), 3);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["This is a new line."],
&["This is new line 2."],
&["这里是第 4 行。New text"],
],
);
// Add a new line at the end
let range = text.len()..text.len();
let new_text = "\nThis is a new line at the end.";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &Rope::from(new_text), &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"This is a new line.\nThis is new line 2.\n这里是第 4 行。New text\nThis is a new line at the end."
);
assert_eq!(wrapper.lines.len(), 4);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["This is a new line."],
&["This is new line 2."],
&["这里是第 4 行。New text"],
&["This is a new line at the end."],
],
);
// Add a new line at the beginning
let range = 0..0;
let new_text = "This is a new line at the beginning.\n";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &Rope::from(new_text), &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"This is a new line at the beginning.\nThis is a new line.\nThis is new line 2.\n这里是第 4 行。New text\nThis is a new line at the end."
);
assert_eq!(wrapper.lines.len(), 5);
assert_wrapper_lines(
&text,
&wrapper,
&[
&["This is a new line at the beginning."],
&["This is a new line."],
&["This is new line 2."],
&["这里是第 4 行。New text"],
&["This is a new line at the end."],
],
);
// Remove all to at least one line in `lines`.
let range = 0..text.len();
let new_text = "";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &Rope::from(new_text), &mut fake_wrap_line);
assert_eq!(text.to_string(), "");
assert_eq!(wrapper.lines.len(), 1);
assert_eq!(wrapper.lines[0].wrapped_lines, vec![0..0]);
// Test update_all
let range = 0..text.len();
let new_text = "This is a full text.\nThis is a second line.";
text.replace(range.clone(), new_text);
wrapper._update(&text, &range, &text, &mut fake_wrap_line);
assert_eq!(
text.to_string(),
"This is a full text.\nThis is a second line."
);
assert_eq!(wrapper.lines.len(), 2);
}
#[test]
fn test_line_layout() {
let mut line_layout = LineLayout::new();
let line1 = ShapedLine::default().with_len(100);
let line2 = ShapedLine::default().with_len(50);
let wrapped_lines = smallvec::smallvec![line1, line2];
line_layout.set_wrapped_lines(wrapped_lines);
assert_eq!(line_layout.len(), 150);
assert_eq!(line_layout.wrapped_lines.len(), 2);
}
#[test]
fn test_position_for_index_prefers_first_leading_empty_visual_line() {
let mut line_layout = LineLayout::new();
line_layout.set_wrapped_lines(smallvec::smallvec![
ShapedLine::default(),
ShapedLine::default(),
ShapedLine::default().with_len(3),
]);
let last_layout = LastLayout {
visible_range: 0..1,
visible_buffer_lines: vec![0],
visible_line_byte_offsets: vec![0],
visible_top: px(0.),
visible_range_offset: 0..0,
lines: Rc::new(vec![]),
line_height: px(20.),
wrap_width: None,
line_number_width: px(0.),
cursor_bounds: None,
text_align: TextAlign::Left,
content_width: px(0.),
};
assert_eq!(
line_layout.position_for_index(0, &last_layout, false),
Some(point(px(0.), px(0.)))
);
}
#[test]
fn test_offset_to_display_point() {
let font = gpui::Font {
family: "Arial".into(),
weight: FontWeight::default(),
style: FontStyle::Normal,
features: FontFeatures::default(),
fallbacks: None,
};
let mut wrapper = TextWrapper::new(font, px(14.), None);
wrapper.text = Rope::from(
"Hello, 世界!\r\nThis is second line.\nThis is third line.\n这里是第 4 行。",
);
wrapper.lines = vec![
// range: 0..15
LineItem {
line: Rope::from("Hello, 世界!\r"),
wrapped_lines: vec![0..15],
},
// range: 16..36
LineItem {
line: Rope::from("This is second line."),
wrapped_lines: vec![0..10, 10..20],
},
// range: 37..56
LineItem {
line: Rope::from("This is third line."),
wrapped_lines: vec![0..9, 9..15, 15..20],
},
// range: 57..79
LineItem {
line: Rope::from("这里是第 4 行。"),
wrapped_lines: vec![0..22],
},
];
assert_eq!(
wrapper.offset_to_display_point(12),
WrapDisplayPoint::new(0, 0, 12)
);
assert_eq!(
wrapper.offset_to_display_point(15),
WrapDisplayPoint::new(0, 0, 15)
);
assert_eq!(
wrapper.offset_to_display_point(16),
WrapDisplayPoint::new(1, 0, 0)
);
assert_eq!(
wrapper.offset_to_display_point(21),
WrapDisplayPoint::new(1, 0, 5)
);
assert_eq!(
wrapper.offset_to_display_point(27),
WrapDisplayPoint::new(2, 1, 1)
);
assert_eq!(
wrapper.offset_to_display_point(37),
WrapDisplayPoint::new(3, 0, 0)
);
assert_eq!(
wrapper.offset_to_display_point(54),
WrapDisplayPoint::new(5, 2, 2)
);
assert_eq!(
wrapper.offset_to_display_point(59),
WrapDisplayPoint::new(6, 0, 2)
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(6, 0, 2)),
59
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(5, 2, 2)),
54
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(3, 0, 0)),
37
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(2, 1, 1)),
27
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(1, 0, 5)),
21
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(1, 0, 0)),
16
);
assert_eq!(
wrapper.display_point_to_offset(WrapDisplayPoint::new(0, 0, 15)),
15
);
}
}

View File

@@ -131,11 +131,14 @@ impl Element for EditorScrollbar {
window: &mut Window,
cx: &mut App,
) -> (LayoutId, Self::RequestLayoutState) {
let mut style = Style::default();
style.position = Position::Absolute;
style.size.width = relative(1.).into();
style.size.height = relative(1.).into();
let style = Style {
position: Position::Absolute,
size: Size {
width: relative(1.).into(),
height: relative(1.).into(),
},
..Default::default()
};
(window.request_layout(style, [], cx), ())
}
@@ -309,13 +312,12 @@ impl TextElement {
let mut cursor_bounds = None;
// If the input has a fixed height (Otherwise is auto-grow), we need to add a bottom margin to the input.
let top_bottom_margin = if state.mode.is_auto_grow() {
line_height
} else if visible_range.len() < BOTTOM_MARGIN_ROWS * 8 {
line_height
} else {
BOTTOM_MARGIN_ROWS * line_height
};
let top_bottom_margin =
if state.mode.is_auto_grow() || visible_range.len() < BOTTOM_MARGIN_ROWS * 8 {
line_height
} else {
BOTTOM_MARGIN_ROWS * line_height
};
// The cursor corresponds to the current cursor position in the text no only the line.
let mut cursor_pos = None;