fix { wrap bug

This commit is contained in:
jess 2026-06-04 13:47:48 -07:00
parent 497323bb00
commit 636137569d
3 changed files with 88 additions and 27 deletions

View File

@ -86,7 +86,10 @@ impl EditorState {
} else { } else {
let editor = self.view_blocks(); let editor = self.view_blocks();
match self.build_free_overlay() { match self.build_free_overlay() {
Some(overlay) => iced_widget::stack![editor, overlay].into(), Some(overlay) => iced_widget::stack![editor, overlay]
.width(Length::Fill)
.height(Length::Fill)
.into(),
None => editor, None => editor,
} }
}; };
@ -146,12 +149,18 @@ impl EditorState {
.into(); .into();
if self.settings_open { if self.settings_open {
return iced_widget::stack![body, self.settings_panel()].into(); return iced_widget::stack![body, self.settings_panel()]
.width(Length::Fill)
.height(Length::Fill)
.into();
} }
#[cfg(any(target_os = "linux", target_os = "windows"))] #[cfg(any(target_os = "linux", target_os = "windows"))]
if let Some(cat) = self.menu_open { if let Some(cat) = self.menu_open {
return iced_widget::stack![body, self.menu_dropdown(cat)].into(); return iced_widget::stack![body, self.menu_dropdown(cat)]
.width(Length::Fill)
.height(Length::Fill)
.into();
} }
body body
@ -376,8 +385,12 @@ impl EditorState {
}; };
let spillover_layer = self.spillover_view().unwrap_or_else(empty_layer); let spillover_layer = self.spillover_view().unwrap_or_else(empty_layer);
// the document scrollable stays at stack layer 0, never re-wrapped by an overlay // the document scrollable stays at stack layer 0, never re-wrapped by an overlay.
iced_widget::stack![inner, selection_tint, minimap_layer, ctx_layer, spillover_layer].into() // a Fill stack gives the scrollable the viewport height, not the zero intrinsic of a Shrink stack
iced_widget::stack![inner, selection_tint, minimap_layer, ctx_layer, spillover_layer]
.width(Length::Fill)
.height(Length::Fill)
.into()
} }
/// builds the right-edge minimap as a clickable AST declaration list. /// builds the right-edge minimap as a clickable AST declaration list.
@ -1443,12 +1456,30 @@ fn splice_first_empty_slot(text: &str, addr: &str) -> Option<String> {
} }
fn macos_key_binding(key_press: KeyPress) -> Option<Binding<Message>> { fn macos_key_binding(key_press: KeyPress) -> Option<Binding<Message>> {
let KeyPress { key, modifiers, status, .. } = &key_press; let KeyPress { key, modified_key, modifiers, status, .. } = &key_press;
if !matches!(status, Status::Focused { .. }) { if !matches!(status, Status::Focused { .. }) {
return None; return None;
} }
// auto-pair resolves from the composed key, not the unshifted base key
if !modifiers.logo() && !modifiers.alt() && !modifiers.control() {
if let keyboard::Key::Character(c) = modified_key.as_ref() {
let pair = match c {
"[" => auto_pair::enabled(auto_pair::BRACKET).then_some(("[", "]")),
"{" => auto_pair::enabled(auto_pair::BRACE).then_some(("{", "}")),
"(" => auto_pair::enabled(auto_pair::PAREN).then_some(("(", ")")),
"'" => auto_pair::enabled(auto_pair::SINGLE).then_some(("'", "'")),
"\"" => auto_pair::enabled(auto_pair::DOUBLE).then_some(("\"", "\"")),
"`" => auto_pair::enabled(auto_pair::BACKTICK).then_some(("`", "`")),
_ => None,
};
if let Some((open, close)) = pair {
return Some(Binding::Custom(Message::AutoPair(open, close)));
}
}
}
match key.as_ref() { match key.as_ref() {
keyboard::Key::Character("z") if modifiers.logo() && modifiers.shift() => { keyboard::Key::Character("z") if modifiers.logo() && modifiers.shift() => {
Some(Binding::Custom(Message::Redo)) Some(Binding::Custom(Message::Redo))
@ -1462,24 +1493,6 @@ fn macos_key_binding(key_press: KeyPress) -> Option<Binding<Message>> {
keyboard::Key::Character("-") if modifiers.logo() => { keyboard::Key::Character("-") if modifiers.logo() => {
Some(Binding::Custom(Message::ZoomOut)) Some(Binding::Custom(Message::ZoomOut))
} }
keyboard::Key::Character("[") if !modifiers.logo() && !modifiers.alt() && !modifiers.control() && auto_pair::enabled(auto_pair::BRACKET) => {
Some(Binding::Custom(Message::AutoPair("[", "]")))
}
keyboard::Key::Character("{") if !modifiers.logo() && !modifiers.alt() && !modifiers.control() && auto_pair::enabled(auto_pair::BRACE) => {
Some(Binding::Custom(Message::AutoPair("{", "}")))
}
keyboard::Key::Character("(") if !modifiers.logo() && !modifiers.alt() && !modifiers.control() && auto_pair::enabled(auto_pair::PAREN) => {
Some(Binding::Custom(Message::AutoPair("(", ")")))
}
keyboard::Key::Character("'") if !modifiers.logo() && !modifiers.alt() && !modifiers.control() && auto_pair::enabled(auto_pair::SINGLE) => {
Some(Binding::Custom(Message::AutoPair("'", "'")))
}
keyboard::Key::Character("\"") if !modifiers.logo() && !modifiers.alt() && !modifiers.control() && auto_pair::enabled(auto_pair::DOUBLE) => {
Some(Binding::Custom(Message::AutoPair("\"", "\"")))
}
keyboard::Key::Character("`") if !modifiers.logo() && !modifiers.alt() && !modifiers.control() && auto_pair::enabled(auto_pair::BACKTICK) => {
Some(Binding::Custom(Message::AutoPair("`", "`")))
}
keyboard::Key::Named(key::Named::Backspace) if modifiers.alt() => { keyboard::Key::Named(key::Named::Backspace) if modifiers.alt() => {
Some(Binding::Sequence(vec![ Some(Binding::Sequence(vec![
Binding::Select(Motion::WordLeft), Binding::Select(Motion::WordLeft),

View File

@ -629,6 +629,54 @@ pub fn render(handle: &mut ViewportHandle) {
); );
handle.events.clear(); handle.events.clear();
#[cfg(debug_assertions)]
{
use std::fmt::Write as _;
use iced_wgpu::core::widget::operation::{Operation, Scrollable};
use iced_wgpu::core::widget::Id as CoreId;
use iced_wgpu::core::{Rectangle, Vector};
let s = &handle.state;
let mut out = String::new();
let _ = writeln!(out, "render_mode={:?} layout={} free_placements={} preview={} settings_open={} font={}",
s.render_mode, s.layout.len(), s.free_placements.len(), s.preview, s.settings_open, s.font_size);
for (i, id) in s.layout.iter().enumerate() {
if let Some(b) = s.registry.get(id) {
let _ = write!(out, " [{i}] id={:?} kind={}", id, b.kind_tag());
if let Some(tb) = b.as_any().downcast_ref::<crate::table_block::TableBlock>() {
let _ = write!(out, " rows={} cols={} widths={:?} read_only={} eval={}",
tb.rows.len(), tb.col_widths.len(), tb.col_widths, tb.read_only, tb.is_eval_result);
}
let _ = writeln!(out);
}
}
// record laid-out bounds of scrollables and the first containers
struct BoundsProbe { scroll: Vec<String>, conts: Vec<String> }
impl Operation<()> for BoundsProbe {
fn traverse(&mut self, operate: &mut dyn FnMut(&mut dyn Operation<()>)) {
operate(self);
}
fn container(&mut self, id: Option<&CoreId>, bounds: Rectangle) {
if self.conts.len() < 24 {
self.conts.push(format!("cont id={:?} x={:.0} y={:.0} w={:.0} h={:.0}",
id, bounds.x, bounds.y, bounds.width, bounds.height));
}
}
fn scrollable(&mut self, id: Option<&CoreId>, bounds: Rectangle, content: Rectangle, tx: Vector, _s: &mut dyn Scrollable) {
self.scroll.push(format!("scroll id={:?} bounds=({:.0},{:.0} {:.0}x{:.0}) content=({:.0},{:.0} {:.0}x{:.0}) tx=({:.0},{:.0})",
id, bounds.x, bounds.y, bounds.width, bounds.height,
content.x, content.y, content.width, content.height, tx.x, tx.y));
}
}
let mut probe = BoundsProbe { scroll: Vec::new(), conts: Vec::new() };
ui.operate(&handle.renderer, &mut probe);
for l in &probe.scroll { let _ = writeln!(out, " {l}"); }
for l in &probe.conts { let _ = writeln!(out, " {l}"); }
let _ = std::fs::write("/tmp/acord-blank.log", out);
}
let focused_id = { let focused_id = {
use iced_wgpu::core::widget::operation::{Focusable, Operation}; use iced_wgpu::core::widget::operation::{Focusable, Operation};
use iced_wgpu::core::widget::Id as CoreId; use iced_wgpu::core::widget::Id as CoreId;

View File

@ -320,7 +320,7 @@ fn wrap_base64(s: &str, width: usize) -> String {
let mut i = 0; let mut i = 0;
while i < bytes.len() { while i < bytes.len() {
let end = (i + width).min(bytes.len()); let end = (i + width).min(bytes.len());
// Base64 is ASCII, slicing by byte == slicing by char. // base64 byte offsets equal char offsets
out.push_str(&s[i..end]); out.push_str(&s[i..end]);
if end < bytes.len() { if end < bytes.len() {
out.push('\n'); out.push('\n');
@ -345,7 +345,7 @@ mod tests {
formulas: HashMap::new(), formulas: HashMap::new(),
}, },
); );
Sidecar { version: 1, tables } Sidecar { version: 1, tables, ..Default::default() }
} }
#[test] #[test]
@ -416,7 +416,7 @@ mod tests {
formulas, formulas,
}, },
); );
let sc = Sidecar { version: 1, tables }; let sc = Sidecar { version: 1, tables, ..Default::default() };
let body = "# Doc\n"; let body = "# Doc\n";
let embedded = embed_archive(body, &sc, &[]); let embedded = embed_archive(body, &sc, &[]);