Skip to content

Commit 7b2c7cd

Browse files
committed
wip; render on changed
1 parent 44ff1a6 commit 7b2c7cd

2 files changed

Lines changed: 95 additions & 2 deletions

File tree

promkit-widgets/src/structured/json/document.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::jsonz::{self, Row, RowOperation};
2+
use crate::structured::ContainerNode;
23

34
/// Represents a navigable JSON document, allowing for efficient row navigation and folding.
45
#[derive(Clone)]
@@ -32,6 +33,11 @@ impl Document {
3233
self.position
3334
}
3435

36+
/// Returns the last visible row position.
37+
pub fn tail_position(&self) -> usize {
38+
self.rows.tail()
39+
}
40+
3541
/// Resolves a visible row offset from the current position into the backing row index.
3642
pub fn visible_offset_to_index(&self, offset: usize) -> Option<usize> {
3743
if self.rows.is_empty() {
@@ -61,6 +67,22 @@ impl Document {
6167
self.position = position.min(self.rows.len().saturating_sub(1));
6268
}
6369

70+
/// Returns whether the current row can be toggled.
71+
pub fn can_toggle_current(&self) -> bool {
72+
self.row_is_toggleable(self.position)
73+
}
74+
75+
/// Returns whether the specified row can be toggled.
76+
pub fn row_is_toggleable(&self, index: usize) -> bool {
77+
matches!(
78+
self.rows.get(index).map(|row| &row.node),
79+
Some(
80+
super::jsonz::JsonNode::Container(ContainerNode::Open { .. })
81+
| super::jsonz::JsonNode::Container(ContainerNode::Close { .. })
82+
)
83+
)
84+
}
85+
6486
/// Sets the visibility of all rows.
6587
pub fn set_nodes_visibility(&mut self, collapsed: bool) {
6688
self.rows.set_rows_visibility(collapsed);

promkit/src/preset/json.rs

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,12 @@ impl crate::Prompt for Json {
6161
}
6262

6363
async fn evaluate(&mut self, event: &Event) -> anyhow::Result<Signal> {
64+
let should_render = self.should_render_after_event(event).await;
6465
let ret = (self.evaluator)(event, self).await;
65-
let size = crossterm::terminal::size()?;
66-
self.render(size.0, size.1).await?;
66+
if should_render {
67+
let size = crossterm::terminal::size()?;
68+
self.render(size.0, size.1).await?;
69+
}
6770
ret
6871
}
6972

@@ -188,4 +191,72 @@ impl Json {
188191
None => Err(anyhow::anyhow!("Renderer not initialized")),
189192
}
190193
}
194+
195+
async fn should_render_after_event(&self, event: &Event) -> bool {
196+
use crate::core::crossterm::event::{
197+
KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers, MouseEvent,
198+
MouseEventKind,
199+
};
200+
201+
match event {
202+
Event::Resize(_, _) => false,
203+
Event::Key(KeyEvent {
204+
code: KeyCode::Up,
205+
modifiers: KeyModifiers::NONE,
206+
kind: KeyEventKind::Press,
207+
state: KeyEventState::NONE,
208+
})
209+
| Event::Mouse(MouseEvent {
210+
kind: MouseEventKind::ScrollUp,
211+
modifiers: KeyModifiers::NONE,
212+
..
213+
}) => self.json.document.position() > 0,
214+
215+
Event::Key(KeyEvent {
216+
code: KeyCode::Down,
217+
modifiers: KeyModifiers::NONE,
218+
kind: KeyEventKind::Press,
219+
state: KeyEventState::NONE,
220+
})
221+
| Event::Mouse(MouseEvent {
222+
kind: MouseEventKind::ScrollDown,
223+
modifiers: KeyModifiers::NONE,
224+
..
225+
}) => self.json.document.position() != self.json.document.tail_position(),
226+
227+
Event::Key(KeyEvent {
228+
code: KeyCode::Char(' '),
229+
modifiers: KeyModifiers::NONE,
230+
kind: KeyEventKind::Press,
231+
state: KeyEventState::NONE,
232+
}) => self.json.document.can_toggle_current(),
233+
234+
Event::Mouse(MouseEvent {
235+
kind: MouseEventKind::Down(_),
236+
column,
237+
row,
238+
modifiers: KeyModifiers::NONE,
239+
}) => {
240+
let Some(renderer) = self.renderer.as_ref() else {
241+
return false;
242+
};
243+
let Some(hit) = renderer.hit_test(*row, *column).await else {
244+
return false;
245+
};
246+
if hit.key != Index::Json {
247+
return false;
248+
}
249+
250+
let Some(index) = self.json.document.visible_offset_to_index(hit.visible_row)
251+
else {
252+
return false;
253+
};
254+
255+
index != self.json.document.position()
256+
|| self.json.document.row_is_toggleable(index)
257+
}
258+
259+
_ => false,
260+
}
261+
}
191262
}

0 commit comments

Comments
 (0)