From 86310c676419c25ee807f714a5ca0c25cd1e0bd9 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Fri, 10 May 2024 12:03:38 +0200 Subject: [PATCH] chore: fix test breaking changes Signed-off-by: kjuulh --- README.md | 2 +- crates/hyperlog-core/src/commander.rs | 22 + crates/hyperlog-core/src/engine.rs | 61 ++- crates/hyperlog-core/src/log.rs | 33 +- crates/hyperlog-core/src/shared_engine.rs | 14 + crates/hyperlog-tui/src/app.rs | 39 +- crates/hyperlog-tui/src/app/dialog.rs | 129 +----- .../src/app/dialog/create_item.rs | 114 ++++++ .../hyperlog-tui/src/app/dialog/edit_item.rs | 138 +++++++ crates/hyperlog-tui/src/command_parser.rs | 2 + crates/hyperlog-tui/src/components.rs | 101 +++-- crates/hyperlog-tui/src/models.rs | 3 + demo.cast | 375 +++++++++++++----- 13 files changed, 763 insertions(+), 270 deletions(-) create mode 100644 crates/hyperlog-tui/src/app/dialog/create_item.rs create mode 100644 crates/hyperlog-tui/src/app/dialog/edit_item.rs diff --git a/README.md b/README.md index 8b47545..da8ecb8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ - [x] Display todos as todos - [x] Create sections -- [ ] Edit todos +- [x] Edit todos - [ ] Move items - [ ] Display summaries and limit todos - [ ] Implement scroll diff --git a/crates/hyperlog-core/src/commander.rs b/crates/hyperlog-core/src/commander.rs index 64a5fa7..94d9e67 100644 --- a/crates/hyperlog-core/src/commander.rs +++ b/crates/hyperlog-core/src/commander.rs @@ -25,6 +25,13 @@ pub enum Command { description: String, state: ItemState, }, + UpdateItem { + root: String, + path: Vec, + title: String, + description: String, + state: ItemState, + }, ToggleItem { root: String, path: Vec, @@ -88,6 +95,21 @@ impl Commander { Command::ToggleItem { root, path } => self .engine .toggle_item(&root, &path.iter().map(|p| p.as_str()).collect::>())?, + Command::UpdateItem { + root, + path, + title, + description, + state, + } => self.engine.update_item( + &root, + &path.iter().map(|p| p.as_str()).collect::>(), + GraphItem::Item { + title, + description, + state, + }, + )?, } self.storage.store(&self.engine)?; diff --git a/crates/hyperlog-core/src/engine.rs b/crates/hyperlog-core/src/engine.rs index 2b89077..a8a5f2f 100644 --- a/crates/hyperlog-core/src/engine.rs +++ b/crates/hyperlog-core/src/engine.rs @@ -44,7 +44,7 @@ impl Engine { match current_item { GraphItem::User(u) => match u.get_mut(section.to_owned()) { Some(graph_item) => { - current_item = graph_item.as_mut(); + current_item = graph_item; } None => anyhow::bail!("path: {} section was not found", section), }, @@ -60,10 +60,10 @@ impl Engine { match current_item { GraphItem::User(u) => { - u.insert(last.to_string(), Box::new(item)); + u.insert(last.to_string(), item); } GraphItem::Section(s) => { - s.insert(last.to_string(), Box::new(item)); + s.insert(last.to_string(), item); } GraphItem::Item { .. } => anyhow::bail!("cannot insert an item into an item"), } @@ -109,11 +109,11 @@ impl Engine { match dest { GraphItem::User(u) => { - u.try_insert(src_item.to_string(), Box::new(src)) + u.try_insert(src_item.to_string(), src) .map_err(|_e| anyhow!("key was already found, aborting: {}", src_item))?; } GraphItem::Section(s) => { - s.try_insert(src_item.to_string(), Box::new(src)) + s.try_insert(src_item.to_string(), src) .map_err(|_e| anyhow!("key was already found, aborting: {}", src_item))?; } GraphItem::Item { .. } => { @@ -145,6 +145,57 @@ impl Engine { Ok(()) } + + pub fn update_item( + &mut self, + root: &str, + path: &[&str], + item: &GraphItem, + ) -> anyhow::Result<()> { + if let Some((name, dest_last)) = path.split_last() { + if let Some(parent) = self.get_mut(root, dest_last) { + match parent { + GraphItem::User(s) | GraphItem::Section(s) => { + if let Some(mut existing) = s.remove(*name) { + match (&mut existing, item) { + ( + GraphItem::Item { + title: ex_title, + description: ex_desc, + state: ex_state, + }, + GraphItem::Item { + title, + description, + state, + }, + ) => { + ex_title.clone_from(title); + ex_desc.clone_from(description); + ex_state.clone_from(state); + + let title = title.replace(".", "-"); + s.insert(title, existing.clone()); + } + _ => { + anyhow::bail!( + "path: {}.{} found is not an item", + root, + path.join(".") + ) + } + } + } + } + GraphItem::Item { .. } => { + anyhow::bail!("cannot rename when item is placed in an item") + } + } + } + } + + Ok(()) + } } impl Display for Engine { diff --git a/crates/hyperlog-core/src/log.rs b/crates/hyperlog-core/src/log.rs index 9bfa142..d9a0efb 100644 --- a/crates/hyperlog-core/src/log.rs +++ b/crates/hyperlog-core/src/log.rs @@ -13,13 +13,19 @@ pub enum ItemState { Done, } +impl Default for ItemState { + fn default() -> Self { + Self::NotDone + } +} + #[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Debug)] #[serde(tag = "type")] pub enum GraphItem { #[serde(rename = "user")] - User(BTreeMap>), + User(BTreeMap), #[serde(rename = "section")] - Section(BTreeMap>), + Section(BTreeMap), #[serde(rename = "item")] Item { title: String, @@ -58,8 +64,7 @@ impl GraphItem { Some((first, rest)) => match self { GraphItem::User(section) | GraphItem::Section(section) => { if rest.is_empty() { - let val = section.remove(*first); - val.map(|v| *v) + section.remove(*first) } else { section.get_mut(*first)?.take(rest) } @@ -131,7 +136,7 @@ mod test { let mut user = BTreeMap::new(); user.insert( "some-project".into(), - Box::new(GraphItem::Section(BTreeMap::default())), + GraphItem::Section(BTreeMap::default()), ); expected.insert("kjuulh".into(), GraphItem::User(user)); @@ -160,13 +165,10 @@ mod test { let mut some_project = BTreeMap::default(); some_project.insert( "some-nested-project".into(), - Box::new(GraphItem::Section(BTreeMap::default())), + GraphItem::Section(BTreeMap::default()), ); let mut user = BTreeMap::new(); - user.insert( - "some-project".into(), - Box::new(GraphItem::Section(some_project)), - ); + user.insert("some-project".into(), GraphItem::Section(some_project)); expected.insert("kjuulh".into(), GraphItem::User(user)); @@ -200,23 +202,20 @@ mod test { let mut nested_project = BTreeMap::default(); nested_project.insert( "some-todo".into(), - Box::new(GraphItem::Item { + GraphItem::Item { title: "some title".into(), description: "some description".into(), state: ItemState::NotDone, - }), + }, ); let mut some_project = BTreeMap::default(); some_project.insert( "some-nested-project".into(), - Box::new(GraphItem::Section(nested_project)), + GraphItem::Section(nested_project), ); let mut user = BTreeMap::new(); - user.insert( - "some-project".into(), - Box::new(GraphItem::Section(some_project)), - ); + user.insert("some-project".into(), GraphItem::Section(some_project)); expected.insert("kjuulh".into(), GraphItem::User(user)); diff --git a/crates/hyperlog-core/src/shared_engine.rs b/crates/hyperlog-core/src/shared_engine.rs index d5edab2..aff0a6f 100644 --- a/crates/hyperlog-core/src/shared_engine.rs +++ b/crates/hyperlog-core/src/shared_engine.rs @@ -49,4 +49,18 @@ impl SharedEngine { Ok(()) } + + pub(crate) fn update_item( + &self, + root: &str, + path: &[&str], + state: GraphItem, + ) -> anyhow::Result<()> { + self.inner + .write() + .unwrap() + .update_item(root, path, &state)?; + + Ok(()) + } } diff --git a/crates/hyperlog-tui/src/app.rs b/crates/hyperlog-tui/src/app.rs index eee5529..68530f9 100644 --- a/crates/hyperlog-tui/src/app.rs +++ b/crates/hyperlog-tui/src/app.rs @@ -1,3 +1,4 @@ +use hyperlog_core::log::GraphItem; use ratatui::{ prelude::*, widgets::{Block, Borders, Padding, Paragraph}, @@ -10,7 +11,10 @@ use crate::{ use self::{ command_bar::{CommandBar, CommandBarState}, - dialog::{CreateItem, CreateItemState}, + dialog::{ + create_item::{CreateItem, CreateItemState}, + edit_item::{EditItem, EditItemState}, + }, }; mod command_bar; @@ -18,12 +22,14 @@ pub mod dialog; pub enum Dialog { CreateItem { state: CreateItemState }, + EditItem { state: EditItemState }, } impl Dialog { pub fn get_command(&self) -> Option { match self { Dialog::CreateItem { state } => state.get_command(), + Dialog::EditItem { state } => state.get_command(), } } } @@ -76,12 +82,13 @@ impl<'a> App<'a> { pub fn update(&mut self, msg: Msg) -> anyhow::Result { tracing::trace!("handling msg: {:?}", msg); - match msg { + match &msg { Msg::MoveRight => self.graph_explorer.move_right()?, Msg::MoveLeft => self.graph_explorer.move_left()?, Msg::MoveDown => self.graph_explorer.move_down()?, Msg::MoveUp => self.graph_explorer.move_up()?, Msg::OpenCreateItemDialog => self.open_dialog(), + Msg::OpenEditItemDialog { item } => self.open_edit_item_dialog(item), Msg::EnterInsertMode => self.mode = Mode::Insert, Msg::EnterViewMode => self.mode = Mode::View, Msg::EnterCommandMode => { @@ -95,7 +102,7 @@ impl<'a> App<'a> { Msg::SubmitCommand { command } => { tracing::info!("submitting command"); - if let Some(command) = CommandParser::parse(&command) { + if let Some(command) = CommandParser::parse(command) { match self.focus { AppFocus::Dialog => { if command.is_write() { @@ -113,7 +120,12 @@ impl<'a> App<'a> { self.dialog = None; } } - AppFocus::Graph => self.graph_explorer.execute_command(&command)?, + AppFocus::Graph => { + if let Some(msg) = self.graph_explorer.execute_command(&command)? { + self.command = None; + return Ok(msg.into_command()); + } + } } } self.command = None; @@ -128,6 +140,7 @@ impl<'a> App<'a> { } else if let Some(dialog) = &mut self.dialog { match dialog { Dialog::CreateItem { state } => state.update(&msg)?, + Dialog::EditItem { state } => state.update(&msg)?, } } @@ -145,6 +158,20 @@ impl<'a> App<'a> { }); } } + + fn open_edit_item_dialog(&mut self, item: &GraphItem) { + if self.dialog.is_none() { + let root = self.root.clone(); + let path = self.graph_explorer.get_current_path(); + + self.dialog = Some(Dialog::EditItem { + state: EditItemState::new(root, path, item), + }); + self.command = None; + self.focus = AppFocus::Dialog; + self.mode = Mode::Insert; + } + } } impl<'a> Widget for &mut App<'a> { @@ -176,6 +203,7 @@ pub fn render_app(frame: &mut Frame, state: &mut App) { match dialog { Dialog::CreateItem { .. } => heading_parts.push(Span::raw("create item")), + Dialog::EditItem { .. } => heading_parts.push(Span::raw("edit item")), } } @@ -238,6 +266,9 @@ pub fn render_app(frame: &mut Frame, state: &mut App) { Dialog::CreateItem { state } => { frame.render_stateful_widget(&mut CreateItem::default(), chunks[1], state) } + Dialog::EditItem { state } => { + frame.render_stateful_widget(&mut EditItem::default(), chunks[1], state) + } } return; diff --git a/crates/hyperlog-tui/src/app/dialog.rs b/crates/hyperlog-tui/src/app/dialog.rs index a3d9e75..9ea4d56 100644 --- a/crates/hyperlog-tui/src/app/dialog.rs +++ b/crates/hyperlog-tui/src/app/dialog.rs @@ -1,4 +1,3 @@ -use itertools::Itertools; use ratatui::{prelude::*, widgets::*}; use crate::models::{EditMsg, Msg}; @@ -74,7 +73,16 @@ pub struct InputBuffer { } impl InputBuffer { - fn transform_focused(&mut self) { + pub fn new(input: String) -> Self { + Self { + state: BufferState::Static { + content: input, + position: 0, + }, + } + } + + pub fn transform_focused(&mut self) { match &mut self.state { BufferState::Focused { .. } => {} BufferState::Static { content, position } => { @@ -136,6 +144,14 @@ impl InputBuffer { BufferState::Static { content, .. } => content.to_owned(), } } + + fn set_position(&mut self, title_len: usize) { + match &mut self.state { + BufferState::Focused { position, .. } | BufferState::Static { position, .. } => { + *position = title_len + } + } + } } pub struct InputField<'a> { @@ -189,110 +205,5 @@ fn clamp_x(area: &Rect, x: u16) -> u16 { } } -enum CreateItemFocused { - Title, - Description, -} -impl Default for CreateItemFocused { - fn default() -> Self { - Self::Title - } -} - -pub struct CreateItemState { - root: String, - path: Vec, - - title: InputBuffer, - description: InputBuffer, - - focused: CreateItemFocused, -} - -impl CreateItemState { - pub fn new(root: impl Into, path: impl IntoIterator>) -> Self { - let root = root.into(); - let path = path.into_iter().map(|p| p.into()).collect_vec(); - - Self { - root, - path, - - title: Default::default(), - description: Default::default(), - focused: Default::default(), - } - } - - pub fn update(&mut self, msg: &Msg) -> anyhow::Result<()> { - match &msg { - Msg::MoveDown | Msg::MoveUp => match self.focused { - CreateItemFocused::Title => self.focused = CreateItemFocused::Description, - CreateItemFocused::Description => self.focused = CreateItemFocused::Title, - }, - _ => {} - } - - match self.focused { - CreateItemFocused::Title => { - self.title.update(msg)?; - } - CreateItemFocused::Description => { - self.description.update(msg)?; - } - } - - Ok(()) - } - - pub fn get_command(&self) -> Option { - let title = self.title.string(); - let description = self.description.string(); - - if !title.is_empty() { - let mut path = self.path.clone(); - path.push(title.replace([' ', '.'], "-")); - - Some(hyperlog_core::commander::Command::CreateItem { - root: self.root.clone(), - path, - title: title.trim().into(), - description: description.trim().into(), - state: hyperlog_core::log::ItemState::NotDone, - }) - } else { - None - } - } -} - -#[derive(Default)] -pub struct CreateItem {} - -impl StatefulWidget for &mut CreateItem { - type State = CreateItemState; - - fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { - let chunks = Layout::vertical(vec![ - Constraint::Length(2), - Constraint::Length(3), - Constraint::Length(3), - ]) - .split(area); - - let path = format!("path: {}.{}", state.root, state.path.join(".")); - let path_header = Paragraph::new(path).dark_gray(); - path_header.render(chunks[0], buf); - - let mut title_input = InputField::new("title"); - let mut description_input = InputField::new("description"); - - match state.focused { - CreateItemFocused::Title => title_input.focused = true, - CreateItemFocused::Description => description_input.focused = true, - } - - title_input.render(chunks[1], buf, &mut state.title); - description_input.render(chunks[2], buf, &mut state.description); - } -} +pub mod create_item; +pub mod edit_item; diff --git a/crates/hyperlog-tui/src/app/dialog/create_item.rs b/crates/hyperlog-tui/src/app/dialog/create_item.rs new file mode 100644 index 0000000..a8e397c --- /dev/null +++ b/crates/hyperlog-tui/src/app/dialog/create_item.rs @@ -0,0 +1,114 @@ +use itertools::Itertools; +use ratatui::{prelude::*, widgets::*}; + +use crate::models::Msg; + +use super::{InputBuffer, InputField}; + +enum CreateItemFocused { + Title, + Description, +} +impl Default for CreateItemFocused { + fn default() -> Self { + Self::Title + } +} + +pub struct CreateItemState { + root: String, + path: Vec, + + title: InputBuffer, + description: InputBuffer, + + focused: CreateItemFocused, +} + +impl CreateItemState { + pub fn new(root: impl Into, path: impl IntoIterator>) -> Self { + let root = root.into(); + let path = path.into_iter().map(|p| p.into()).collect_vec(); + + Self { + root, + path, + + title: Default::default(), + description: Default::default(), + focused: Default::default(), + } + } + + pub fn update(&mut self, msg: &Msg) -> anyhow::Result<()> { + match &msg { + Msg::MoveDown | Msg::MoveUp => match self.focused { + CreateItemFocused::Title => self.focused = CreateItemFocused::Description, + CreateItemFocused::Description => self.focused = CreateItemFocused::Title, + }, + _ => {} + } + + match self.focused { + CreateItemFocused::Title => { + self.title.update(msg)?; + } + CreateItemFocused::Description => { + self.description.update(msg)?; + } + } + + Ok(()) + } + + pub fn get_command(&self) -> Option { + let title = self.title.string(); + let description = self.description.string(); + + if !title.is_empty() { + let mut path = self.path.clone(); + path.push(title.replace([' ', '.'], "-")); + + Some(hyperlog_core::commander::Command::CreateItem { + root: self.root.clone(), + path, + title: title.trim().into(), + description: description.trim().into(), + state: hyperlog_core::log::ItemState::NotDone, + }) + } else { + None + } + } +} + +#[derive(Default)] +pub struct CreateItem {} + +impl StatefulWidget for &mut CreateItem { + type State = CreateItemState; + + fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { + let chunks = Layout::vertical(vec![ + Constraint::Length(2), + Constraint::Length(3), + Constraint::Length(3), + ]) + .split(area); + + let path = format!("path: {}.{}", state.root, state.path.join(".")); + let path_header = Paragraph::new(path).dark_gray(); + path_header.render(chunks[0], buf); + + let mut title_input = InputField::new("title"); + let mut description_input = InputField::new("description"); + + match state.focused { + CreateItemFocused::Title => title_input.focused = true, + CreateItemFocused::Description => description_input.focused = true, + } + + title_input.render(chunks[1], buf, &mut state.title); + description_input.render(chunks[2], buf, &mut state.description); + } +} diff --git a/crates/hyperlog-tui/src/app/dialog/edit_item.rs b/crates/hyperlog-tui/src/app/dialog/edit_item.rs new file mode 100644 index 0000000..2e364f3 --- /dev/null +++ b/crates/hyperlog-tui/src/app/dialog/edit_item.rs @@ -0,0 +1,138 @@ +use hyperlog_core::log::GraphItem; +use itertools::Itertools; +use ratatui::{prelude::*, widgets::*}; + +use crate::models::Msg; + +use super::{InputBuffer, InputField}; + +enum EditItemFocused { + Title, + Description, +} +impl Default for EditItemFocused { + fn default() -> Self { + Self::Title + } +} + +pub struct EditItemState { + root: String, + path: Vec, + + title: InputBuffer, + description: InputBuffer, + + item: GraphItem, + + focused: EditItemFocused, +} + +impl EditItemState { + pub fn new( + root: impl Into, + path: impl IntoIterator>, + item: &GraphItem, + ) -> Self { + let root = root.into(); + let path = path.into_iter().map(|p| p.into()).collect_vec(); + + match item { + GraphItem::Item { + title, description, .. + } => { + let title_len = title.len(); + let mut title = InputBuffer::new(title.clone()); + title.transform_focused(); + title.set_position(title_len); + + Self { + root, + path, + + item: item.clone(), + + title, + description: InputBuffer::new(description.clone()), + focused: Default::default(), + } + } + _ => todo!("cannot edit item from other than GraphItem::Item"), + } + } + + pub fn update(&mut self, msg: &Msg) -> anyhow::Result<()> { + match &msg { + Msg::MoveDown | Msg::MoveUp => match self.focused { + EditItemFocused::Title => self.focused = EditItemFocused::Description, + EditItemFocused::Description => self.focused = EditItemFocused::Title, + }, + _ => {} + } + + match self.focused { + EditItemFocused::Title => { + self.title.update(msg)?; + } + EditItemFocused::Description => { + self.description.update(msg)?; + } + } + + Ok(()) + } + + pub fn get_command(&self) -> Option { + let title = self.title.string(); + let description = self.description.string(); + + if !title.is_empty() { + let path = self.path.clone(); + + Some(hyperlog_core::commander::Command::UpdateItem { + root: self.root.clone(), + path, + title: title.trim().into(), + description: description.trim().into(), + state: match &self.item { + GraphItem::User(_) => Default::default(), + GraphItem::Section(_) => Default::default(), + GraphItem::Item { state, .. } => state.clone(), + }, + }) + } else { + None + } + } +} + +#[derive(Default)] +pub struct EditItem {} + +impl StatefulWidget for &mut EditItem { + type State = EditItemState; + + fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { + let chunks = Layout::vertical(vec![ + Constraint::Length(2), + Constraint::Length(3), + Constraint::Length(3), + ]) + .split(area); + + let path = format!("path: {}.{}", state.root, state.path.join(".")); + let path_header = Paragraph::new(path).dark_gray(); + path_header.render(chunks[0], buf); + + let mut title_input = InputField::new("title"); + let mut description_input = InputField::new("description"); + + match state.focused { + EditItemFocused::Title => title_input.focused = true, + EditItemFocused::Description => description_input.focused = true, + } + + title_input.render(chunks[1], buf, &mut state.title); + description_input.render(chunks[2], buf, &mut state.description); + } +} diff --git a/crates/hyperlog-tui/src/command_parser.rs b/crates/hyperlog-tui/src/command_parser.rs index 4e348b9..2d25d9d 100644 --- a/crates/hyperlog-tui/src/command_parser.rs +++ b/crates/hyperlog-tui/src/command_parser.rs @@ -6,6 +6,7 @@ pub enum Commands { WriteQuit, Archive, CreateSection { name: String }, + Edit, } impl Commands { @@ -35,6 +36,7 @@ impl CommandParser { "cs" | "create-section" => rest.first().map(|name| Commands::CreateSection { name: name.to_string(), }), + "e" | "edit" => Some(Commands::Edit), _ => None, }, None => None, diff --git a/crates/hyperlog-tui/src/components.rs b/crates/hyperlog-tui/src/components.rs index f466f53..755e321 100644 --- a/crates/hyperlog-tui/src/components.rs +++ b/crates/hyperlog-tui/src/components.rs @@ -5,7 +5,7 @@ use hyperlog_core::log::{GraphItem, ItemState}; use itertools::Itertools; use ratatui::{prelude::*, widgets::*}; -use crate::{command_parser::Commands, state::SharedState}; +use crate::{command_parser::Commands, models::Msg, state::SharedState}; pub struct GraphExplorer<'a> { state: SharedState, @@ -145,7 +145,17 @@ impl<'a> GraphExplorer<'a> { } } - pub fn execute_command(&mut self, command: &Commands) -> anyhow::Result<()> { + fn get_current_item(&self) -> Option { + let graph = self.linearize_graph(); + + if let Some(graph) = graph { + graph.get_graph_item(&self.inner.current_position).cloned() + } else { + None + } + } + + pub fn execute_command(&mut self, command: &Commands) -> anyhow::Result> { match command { Commands::Archive => { if !self.get_current_path().is_empty() { @@ -165,12 +175,35 @@ impl<'a> GraphExplorer<'a> { )?; } } + Commands::Edit => { + if let Some(item) = self.get_current_item() { + let path = self.get_current_path(); + + tracing::debug!( + "found item to edit: path: {}, item: {}", + path.join("."), + item.name + ); + match item.item_type { + GraphItemType::Section => { + todo!("cannot edit section at the moment") + } + GraphItemType::Item { .. } => { + if let Some(item) = self.state.querier.get(&self.inner.root, path) { + if let GraphItem::Item { .. } = item { + return Ok(Some(Msg::OpenEditItemDialog { item })); + } + } + } + } + } + } _ => (), } self.update_graph()?; - Ok(()) + Ok(None) } pub(crate) fn interact(&mut self) -> anyhow::Result<()> { @@ -240,7 +273,7 @@ impl RenderGraph for MovementGraph { let embedded_sections = item.values.render_graph_spans(rest); for section in &embedded_sections { - let mut line = vec![Span::raw(" ")]; + let mut line = vec![Span::raw(" ".repeat(4))]; line.extend_from_slice(section); lines.push(Line::from(line)); } @@ -255,7 +288,7 @@ impl RenderGraph for MovementGraph { let embedded_sections = item.values.render_graph_spans(&[]); for section in &embedded_sections { - let mut line = vec![Span::raw(" ")]; + let mut line = vec![Span::raw(" ".repeat(4))]; line.extend_from_slice(section); lines.push(Line::from(line)); } @@ -306,7 +339,7 @@ impl RenderGraph for MovementGraph { let embedded_sections = item.values.render_graph_spans(rest); for section in &embedded_sections { - let mut line = vec![Span::raw(" ")]; + let mut line = vec![Span::raw(" ".repeat(4))]; line.extend_from_slice(section); lines.push(line); } @@ -319,7 +352,7 @@ impl RenderGraph for MovementGraph { let embedded_sections = item.values.render_graph_spans(&[]); for section in &embedded_sections { - let mut line = vec![Span::raw(" ")]; + let mut line = vec![Span::raw(" ".repeat(4))]; line.extend_from_slice(section); lines.push(line); } @@ -396,7 +429,7 @@ impl MovementGraph { fn next_down(&self, items: &[usize]) -> Option> { match items.split_last() { Some((current_index, rest)) => { - if let Some(current_item) = self.get_graph_item(rest) { + if let Some(current_item) = self.get_graph(rest) { if *current_index + 1 < current_item.items.len() { let mut vec = rest.to_vec(); vec.push(current_index + 1); @@ -415,16 +448,29 @@ impl MovementGraph { } } - fn get_graph_item(&self, items: &[usize]) -> Option<&MovementGraph> { + fn get_graph(&self, items: &[usize]) -> Option<&MovementGraph> { match items.split_first() { Some((first, rest)) => match self.items.get(*first).map(|s| &s.values) { - Some(next_graph) => next_graph.get_graph_item(rest), + Some(next_graph) => next_graph.get_graph(rest), None => Some(self), }, None => Some(self), } } + fn get_graph_item(&self, items: &[usize]) -> Option<&MovementGraphItem> { + match items.split_first() { + Some((first, rest)) => match self.items.get(*first) { + Some(next_graph) => match next_graph.values.get_graph_item(rest) { + Some(graph_item) => Some(graph_item), + None => Some(next_graph), + }, + None => None, + }, + None => None, + } + } + fn to_current_path(&self, position_items: &[usize]) -> Vec { match position_items.split_first() { Some((first, rest)) => match self.items.get(*first) { @@ -462,7 +508,7 @@ impl From for MovementGraph { index: i, name: key.clone(), values: value.clone().into(), - item_type: match value.deref() { + item_type: match value { GraphItem::User(_) => GraphItemType::Section, GraphItem::Section(_) => GraphItemType::Section, GraphItem::Item { state, .. } => GraphItemType::Item { @@ -522,33 +568,30 @@ mod test { fn test_can_transform_to_movement_graph() { let graph = GraphItem::User(BTreeMap::from([( "0".to_string(), - Box::new(GraphItem::Section(BTreeMap::from([ - ( - "00".to_string(), - Box::new(GraphItem::Section(BTreeMap::new())), - ), + GraphItem::Section(BTreeMap::from([ + ("00".to_string(), GraphItem::Section(BTreeMap::new())), ( "01".to_string(), - Box::new(GraphItem::Section(BTreeMap::from([ + GraphItem::Section(BTreeMap::from([ ( "010".to_string(), - Box::new(GraphItem::Item { + GraphItem::Item { title: "some-title".into(), description: "some-desc".into(), state: ItemState::NotDone, - }), + }, ), ( "011".to_string(), - Box::new(GraphItem::Item { + GraphItem::Item { title: "some-title".into(), description: "some-desc".into(), state: ItemState::NotDone, - }), + }, ), - ]))), + ])), ), - ]))), + ])), )])); let actual: MovementGraph = graph.into(); @@ -672,16 +715,16 @@ mod test { ], }; - let actual_default = graph.get_graph_item(&[]); + let actual_default = graph.get_graph(&[]); assert_eq!(Some(&graph), actual_default); - let actual_first = graph.get_graph_item(&[0]); + let actual_first = graph.get_graph(&[0]); assert_eq!(graph.items.first().map(|i| &i.values), actual_first); - let actual_second = graph.get_graph_item(&[1]); + let actual_second = graph.get_graph(&[1]); assert_eq!(graph.items.get(1).map(|i| &i.values), actual_second); - let actual_nested = graph.get_graph_item(&[0, 0]); + let actual_nested = graph.get_graph(&[0, 0]); assert_eq!( graph .items @@ -691,7 +734,7 @@ mod test { actual_nested ); - let actual_nested = graph.get_graph_item(&[0, 1]); + let actual_nested = graph.get_graph(&[0, 1]); assert_eq!( graph .items @@ -701,7 +744,7 @@ mod test { actual_nested ); - let actual_nested = graph.get_graph_item(&[1, 2]); + let actual_nested = graph.get_graph(&[1, 2]); assert_eq!( graph .items diff --git a/crates/hyperlog-tui/src/models.rs b/crates/hyperlog-tui/src/models.rs index 095be5c..7978b66 100644 --- a/crates/hyperlog-tui/src/models.rs +++ b/crates/hyperlog-tui/src/models.rs @@ -1,3 +1,5 @@ +use hyperlog_core::log::GraphItem; + use crate::commands::{Command, IntoCommand}; #[derive(Debug)] @@ -7,6 +9,7 @@ pub enum Msg { MoveDown, MoveUp, OpenCreateItemDialog, + OpenEditItemDialog { item: GraphItem }, Interact, EnterInsertMode, diff --git a/demo.cast b/demo.cast index e4ddff9..1630fa3 100644 --- a/demo.cast +++ b/demo.cast @@ -1,105 +1,270 @@ -{"version": 2, "width": 106, "height": 35, "timestamp": 1715268076, "env": {"SHELL": "/usr/bin/zsh", "TERM": "alacritty"}} -[0.061956, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] -[0.108311, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\r\n\u001b[38;2;255;153;102mhyperlog\u001b[0m \u001b[90mmain\u001b[0m\u001b[38;2;255;153;102m \u001b[0m\u001b[38;2;255;153;102m≡ \u001b[0m\u001b[1;31mrs \u001b[0m\r\n\u001b[38;2;255;153;102m❯\u001b[0m \u001b[K"] -[0.108972, "o", "\u001b[6 q"] -[0.109631, "o", "\u001b[6 q"] -[0.109701, "o", "\u001b[?2004h"] -[1.076184, "o", "c"] -[1.077952, "o", "\b\u001b[32mc\u001b[39m"] -[1.099899, "o", "\b\u001b[32mc\u001b[39m\u001b[90mlear\u001b[39m\b\b\b\b"] -[1.16562, "o", "\b\u001b[32mc\u001b[32ma\u001b[39m\u001b[39m \u001b[39m \u001b[39m \b\b\b"] -[1.170777, "o", "\b\b\u001b[1m\u001b[31mc\u001b[1m\u001b[31ma\u001b[0m\u001b[39m"] -[1.179169, "o", "\u001b[90mrgo clean\u001b[39m\u001b[9D"] -[1.254615, "o", "\b\b\u001b[1m\u001b[31mc\u001b[1m\u001b[31ma\u001b[1m\u001b[31mr\u001b[0m\u001b[39m"] -[1.404835, "o", "\b\u001b[1m\u001b[31mr\u001b[1m\u001b[31mg\u001b[0m\u001b[39m"] -[1.511465, "o", "\b\u001b[1m\u001b[31mg\u001b[1m\u001b[31mo\u001b[0m\u001b[39m"] -[1.512482, "o", "\b\b\b\b\b\u001b[0m\u001b[32mc\u001b[0m\u001b[32ma\u001b[0m\u001b[32mr\u001b[0m\u001b[32mg\u001b[0m\u001b[32mo\u001b[39m"] -[1.554502, "o", "\b\u001b[32mo\u001b[32m \u001b[39m"] -[1.555456, "o", "\b\b\u001b[32mo\u001b[39m\u001b[39m "] -[1.722553, "o", "\u001b[39mr\u001b[39m \u001b[39m \u001b[39m \u001b[39m \b\b\b\b"] -[1.724362, "o", "\b\u001b[4mr\u001b[24m"] -[1.742164, "o", "\u001b[90mun\u001b[39m\b\b"] -[1.811359, "o", "\b\u001b[4mr\u001b[39m\u001b[4mu\u001b[24m"] -[1.813462, "o", "\b\b\u001b[24mr\u001b[24mu"] -[1.961913, "o", "\u001b[39mn"] -[2.158475, "o", "\u001b[0 q"] -[2.158606, "o", "\u001b[?2004l\r\r\n"] -[2.309291, "o", "\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `Commands`\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0mcrates/hyperlog-tui/src/app.rs:7:37\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m7\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m command_parser::{CommandParser, Commands},\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_imports)]` on by default\u001b[0m\r\n\r\n\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: method `toggle` is never used\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0mcrates/hyperlog-tui/src/app/dialog.rs:100:12\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m75\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0mimpl InputBuffer {\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m----------------\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12mmethod in this implementation\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m...\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m100\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m pub fn toggle(&mut self) {\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(dead_code)]` on by default\u001b[0m\r\n\r\n\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m:\u001b[0m `hyperlog-tui` (lib) generated 2 warnings (run `cargo fix --lib -p hyperlog-tui` to apply 1 suggestion)\r\n\u001b[1m\u001b[32m Finished\u001b[0m \u001b]8;;https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles\u001b\\`dev` profile [unoptimized + debuginfo]\u001b]8;;\u001b\\ target(s) in 0.09s\r\n"] -[2.315705, "o", "\u001b[1m\u001b[32m Running\u001b[0m `target/debug/hyperlog`\r\n"] -[2.324861, "o", "\u001b[?1049h"] -[2.327382, "o", "\u001b[1;1H\u001b[38;5;2mhyperlog\u001b[2;1H\u001b[39m──────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[3;1H\u001b[38;5;8m- other\u001b[5;3H- other\u001b[7;5H- other\u001b[9;7H- [ ] a\u001b[11;5H- [ ] something\u001b[13;1H- some\u001b[15;1H- something\u001b[17;3H- else\u001b[19;3H- third\u001b[35;2H\u001b[39m--\u001b[35;5HVIEW\u001b[35;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[2.579631, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[2.83217, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[3.084795, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[3.117018, "o", "\u001b[3;1H\u001b[1m\u001b[38;5;15m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[3.37073, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[3.506269, "o", "\u001b[3;1H\u001b[38;5;8m- other\u001b[13;1H\u001b[1m\u001b[38;5;15m- some\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[3.759095, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.011929, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.047613, "o", "\u001b[3;1H\u001b[1m\u001b[38;5;15m- other\u001b[13;1H\u001b[22m\u001b[38;5;8m- some\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.300637, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.304359, "o", "\u001b[3;1H\u001b[38;5;8m- other\u001b[5;3H\u001b[1m\u001b[38;5;15m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.557092, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.737839, "o", "\u001b[1;10H~\u001b[1;12Hcreate\u001b[1;19Hitem\u001b[3;1H┌title───────────────────────────────────────────────────────────────────────────────────────────────────┐\u001b[4;1H│\u001b[38;5;0m\u001b[48;5;5m \u001b[4;106H\u001b[39m\u001b[49m│\u001b[5;1H└────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[6;1H\u001b[38;5;8m┌description────────────────────────────────────────────────────────────────────────────────────────────"] -[4.737887, "o", "─┐\u001b[7;1H│ \u001b[7;7H │\u001b[8;1H└────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[9;7H\u001b[39m \u001b[11;5H \u001b[13;1H \u001b[15;1H \u001b[17;3H \u001b[19;3H \u001b[35;5HEDIT\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[4.990266, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.242663, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.263649, "o", "\u001b[4;2Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.336941, "o", "\u001b[4;3Ho\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.473386, "o", "\u001b[4;4Hm\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.546165, "o", "\u001b[4;5He\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.684402, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[5.937063, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[6.189562, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[6.442354, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[6.694082, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[6.809652, "o", "\u001b[4;6H \u001b[35;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.062032, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.106297, "o", "\u001b[35;1H: \u001b[35;5H \u001b[35;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.196456, "o", "\u001b[35;2Hw\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.255925, "o", "\u001b[35;3Hq\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.467764, "o", "\u001b[1;10H \u001b[1;12H \u001b[1;19H \u001b[3;1H\u001b[38;5;8m- other\u001b[39m \u001b[4;1H \u001b[4;106H \u001b[5;1H \u001b[1m\u001b[38;5;15m- other\u001b[22m\u001b[39m \u001b[6;1H \u001b[7;1H \u001b[38;5;8m-\u001b[7;7Hother\u001b[39m \u001b[8;1H \u001b[9;7H\u001b[38;5;8m- [ ] a\u001b[11;5H- [ ] some\u001b[13;5H- [ ] something\u001b[15;1H- some\u001b[17;1H- something\u001b[19;3H- else\u001b[21;3H- third\u001b[35;1H\u001b[39m --\u001b[35;5HVIEW\u001b[35;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.720604, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[7.973639, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[8.226784, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[8.336689, "o", "\u001b[5;3H\u001b[38;5;8m- other\u001b[7;5H\u001b[1m\u001b[38;5;15m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[8.590186, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[8.773505, "o", "\u001b[7;5H\u001b[38;5;8m- other\u001b[9;7H\u001b[1m\u001b[38;5;15m- [ ] a\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[9.026085, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[9.17675, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[9.429584, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[9.643372, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[9.896858, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[9.926048, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[10.178828, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[10.273339, "o", "\u001b[7;5H\u001b[1m\u001b[38;5;15m- other\u001b[9;7H\u001b[22m\u001b[38;5;8m- [ ] a\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[10.52597, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[10.5434, "o", "\u001b[7;5H\u001b[38;5;8m- other\u001b[11;5H\u001b[1m\u001b[38;5;15m- [ ] some\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[10.796065, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[11.04899, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[11.302034, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[11.554807, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[11.697704, "o", "\u001b[11;8H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[11.951284, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[12.205311, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[12.373535, "o", "\u001b[11;5H\u001b[38;5;8m- [x] some\u001b[13;5H\u001b[1m\u001b[38;5;15m- [ ] something\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[12.626159, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[12.823931, "o", "\u001b[13;8H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.07613, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.09335, "o", "\u001b[11;5H\u001b[1m\u001b[38;5;15m- [x] some\u001b[13;5H\u001b[22m\u001b[38;5;8m- [x] something\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.287478, "o", "\u001b[7;5H\u001b[1m\u001b[38;5;15m- other\u001b[11;5H\u001b[22m\u001b[38;5;8m- [x] some\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.540166, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.573087, "o", "\u001b[7;5H\u001b[38;5;8m- other\u001b[9;7H\u001b[1m\u001b[38;5;15m- [ ] a\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.826053, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[13.903827, "o", "\u001b[9;10H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[14.156497, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[14.367096, "o", "\u001b[7;5H\u001b[1m\u001b[38;5;15m- other\u001b[9;7H\u001b[22m\u001b[38;5;8m- [x] a\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[14.594457, "o", "\u001b[5;3H\u001b[1m\u001b[38;5;15m- other\u001b[7;5H\u001b[22m\u001b[38;5;8m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[14.847965, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] -[15.025229, "o", "\u001b[?1049l\u001b[?25h"] -[15.026982, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] -[15.04886, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\r\n\u001b[38;2;255;153;102mhyperlog\u001b[0m \u001b[90mmain\u001b[0m\u001b[38;2;255;153;102m \u001b[0m\u001b[38;2;255;153;102m≡ \u001b[0m\u001b[1;31mrs \u001b[0m\u001b[33m12s\u001b[0m \r\n\u001b[38;2;255;153;102m❯\u001b[0m \u001b[K"] -[15.049561, "o", "\u001b[6 q"] -[15.05028, "o", "\u001b[6 q"] -[15.050378, "o", "\u001b[?2004h"] -[16.301699, "o", "\u001b[?2004l\r\r\n"] +{"version": 2, "width": 209, "height": 37, "timestamp": 1715275908, "env": {"SHELL": "/usr/bin/zsh", "TERM": "alacritty"}} +[0.068021, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[0.116188, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\r\n\u001b[38;2;255;153;102mhyperlog\u001b[0m \u001b[90mmain\u001b[0m\u001b[38;2;255;153;102m \u001b[0m\u001b[38;2;255;153;102m≡ \u001b[0m\u001b[1;31mrs \u001b[0m\r\n\u001b[38;2;255;153;102m❯\u001b[0m \u001b[K"] +[0.116811, "o", "\u001b[6 q"] +[0.117407, "o", "\u001b[6 q"] +[0.117474, "o", "\u001b[?2004h"] +[1.422226, "o", "c"] +[1.424015, "o", "\b\u001b[32mc\u001b[39m"] +[1.443117, "o", "\b\u001b[32mc\u001b[39m\u001b[90margo run\u001b[39m\u001b[8D"] +[1.524895, "o", "\b\u001b[32mc\u001b[32ma\u001b[39m"] +[1.530521, "o", "\b\b\u001b[1m\u001b[31mc\u001b[1m\u001b[31ma\u001b[0m\u001b[39m"] +[1.584427, "o", "\b\b\u001b[1m\u001b[31mc\u001b[1m\u001b[31ma\u001b[1m\u001b[31mr\u001b[0m\u001b[39m"] +[1.764701, "o", "\b\u001b[1m\u001b[31mr\u001b[1m\u001b[31mg\u001b[0m\u001b[39m"] +[1.867961, "o", "\b\u001b[1m\u001b[31mg\u001b[1m\u001b[31mo\u001b[0m\u001b[39m"] +[1.869689, "o", "\b\b\b\b\b\u001b[0m\u001b[32mc\u001b[0m\u001b[32ma\u001b[0m\u001b[32mr\u001b[0m\u001b[32mg\u001b[0m\u001b[32mo\u001b[39m"] +[1.945386, "o", "\b\u001b[32mo\u001b[32m \u001b[39m"] +[1.946701, "o", "\b\b\u001b[32mo\u001b[39m\u001b[39m "] +[2.048502, "o", "\u001b[39mr"] +[2.050856, "o", "\b\u001b[4mr\u001b[24m"] +[2.155029, "o", "\b\u001b[4mr\u001b[39m\u001b[4mu\u001b[24m"] +[2.156838, "o", "\b\b\u001b[24mr\u001b[24mu"] +[2.317861, "o", "\u001b[39mn"] +[2.381304, "o", "\u001b[0 q"] +[2.381438, "o", "\u001b[?2004l\r\r\n"] +[2.553891, "o", "\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `EditMsg`\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0mcrates/hyperlog-tui/src/app/dialog/create_item.rs:4:21\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m4\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::models::{EditMsg, Msg};\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_imports)]` on by default\u001b[0m\r\n\r\n\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `EditMsg`\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0mcrates/hyperlog-tui/src/app/dialog/edit_item.rs:5:21\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m5\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse crate::models::{EditMsg, Msg};\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^\u001b[0m\r\n\r\n\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused import: `itertools::Itertools`\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0mcrates/hyperlog-tui/src/app/dialog.rs:1:5\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m1\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0muse itertools::Itertools;\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^^^^^^^^^^^^^\u001b[0m\r\n\r\n\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: call to `.deref()` on a reference in this situation does nothing\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0mcrates/hyperlog-tui/src/components.rs:514:47\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m514\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m item_type: match value.deref() {\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^^^^^^\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: the type `GraphItem` does not implement `Deref`, so calling `deref` on `&GraphItem` copies the reference, which does not do anything and can be removed\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(noop_method_call)]` on by default\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: remove this redundant call\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m514\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;9m- \u001b[0m\u001b[0m item_type: match value\u001b[0m\u001b[0m\u001b[38;5;9m.deref()\u001b[0m\u001b[0m {\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m514\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ \u001b[0m\u001b[0m item_type: match value {\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;14mhelp\u001b[0m\u001b[0m: if you meant to clone `GraphItem`, implement `Clone` for it\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0m/home/kjuulh/git/git.front.kjuulh.io/kjuulh/hyperlog/crates/hyperlog-core/src/log.rs:24:1\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m24\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[38;5;10m+ #[derive(Clone)]\u001b[0m\r\n\u001b[0m\u001b[1m\u001b[38;5;12m25\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m| \u001b[0m\u001b[0mpub enum GraphItem {\u001b[0m\r\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\r\n\r\n"] +[2.553991, "o", "\u001b[1m\u001b[33mwarning\u001b[0m\u001b[1m:\u001b[0m `hyperlog-tui` (lib) generated 4 warnings (run `cargo fix --lib -p hyperlog-tui` to apply 3 suggestions)\r\n\u001b[1m\u001b[32m Finished\u001b[0m \u001b]8;;https://doc.rust-lang.org/cargo/reference/profiles.html#default-profiles\u001b\\`dev` profile [unoptimized + debuginfo]\u001b]8;;\u001b\\ target(s) in 0.10s\r\n"] +[2.561394, "o", "\u001b[1m\u001b[32m Running\u001b[0m `target/debug/hyperlog`\r\n"] +[2.571775, "o", "\u001b[?1049h"] +[2.576415, "o", "\u001b[1;1H\u001b[38;5;2mhyperlog\u001b[2;1H\u001b[39m─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\u001b[3;1H\u001b[38;5;8m- other\u001b[5;5H- other\u001b[7;9H- other\u001b[9;13H- [x] basdfasdfasdfasdf\u001b[11;13H- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[13;9H- [x] some\u001b[15;9H- something\u001b[17;13H- something-else\u001b[19;17H- [x] another-real-item-man\u001b[21;17H- [x] arealitembaby\u001b[23;9H- [ ] whatever\u001b[25;1H- some\u001b[27;1H- something\u001b[29;5H- else\u001b[31;5H- third\u001b[33;1H- with-something\u001b[37;2H\u001b[39m--\u001b[37;5HVIEW\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[2.830216, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[3.083824, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[3.312323, "o", "\u001b[3;1H\u001b[1m\u001b[38;5;15m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[3.448917, "o", "\u001b[3;1H\u001b[38;5;8m- other\u001b[5;5H\u001b[1m\u001b[38;5;15m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[3.613553, "o", "\u001b[5;5H\u001b[38;5;8m- other\u001b[7;9H\u001b[1m\u001b[38;5;15m- other\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[3.870231, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[3.882483, "o", "\u001b[1;10H~\u001b[1;12Hcreate\u001b[1;19Hitem\u001b[3;1H\u001b[38;5;8mpath: kjuulh.other.other.other \u001b[4;1H \u001b[5;1H\u001b[39m┌title──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[3.88257, "o", "────────────────────────┐\u001b[6;1H│\u001b[38;5;0m\u001b[48;5;5m \u001b[6;209H\u001b[39m\u001b[49m│\u001b[7;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[8;1H\u001b[38;5;8m┌description───────────────────────────────────────────────────────────────────────────────"] +[3.882597, "o", "─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐\u001b[9;1H│ \u001b[9;15H \u001b[9;19H │\u001b[10;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[3.882674, "o", "────────────────────────────────────────────────────────────────┘\u001b[11;13H\u001b[39m \u001b[13;9H \u001b[15;9H \u001b[17;13H \u001b[19;17H \u001b[21;17H \u001b[23;9H \u001b[25;1H \u001b[27;1H \u001b[29;5H \u001b[31;5H \u001b[33;1H \u001b[37;5HEDIT\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.13608, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.388789, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.425751, "o", "\u001b[6;2Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.527752, "o", "\u001b[6;3Ho\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.678825, "o", "\u001b[6;4Hm\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.756198, "o", "\u001b[6;5He\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.845317, "o", "\u001b[6;6Ht\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[4.931464, "o", "\u001b[6;7Hh\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.084899, "o", "\u001b[6;8Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.188535, "o", "\u001b[6;9Hn\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.339409, "o", "\u001b[6;10Hg\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.458766, "o", "\u001b[6;11H \u001b[37;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.711976, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.787803, "o", "\u001b[37;1H: \u001b[37;5H \u001b[37;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.909531, "o", "\u001b[37;2Hw\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[5.985516, "o", "\u001b[37;3Hq\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[6.120986, "o", "\u001b[1;10H \u001b[1;12H \u001b[1;19H \u001b[3;1H\u001b[38;5;8m- other\u001b[39m \u001b[4;1H \u001b[5;1H \u001b[38;5;8m- other\u001b[39m \u001b[6;1H \u001b[6;209H \u001b[7;1H \u001b[1m\u001b[38;5;15m- other\u001b[22m\u001b[39m \u001b[8;1H "] +[6.121104, "o", " \u001b[9;1H \u001b[38;5;8m-\u001b[9;15H[x]\u001b[9;19Hbasdfasdfasdfasdf\u001b[39m \u001b[10;1H \u001b[11;13H\u001b[38;5;8m- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[13;13H- [ ] something\u001b[15;9H- [x] some\u001b[17;9H- something\u001b[19;13H- something-else\u001b[21;17H- [x] another-real-item-man\u001b[23;17H- [x] arealitembaby\u001b[25;9H- [ ] whatever\u001b[27;1H- some\u001b[29;1H- something\u001b[31;5H- else\u001b[33;5H- third\u001b[35;1H- with-something\u001b[37;1H\u001b[39m --\u001b[37;5HVIEW\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[6.376468, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[6.631583, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[6.886855, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[7.049312, "o", "\u001b[7;9H\u001b[38;5;8m- other\u001b[9;13H\u001b[1m\u001b[38;5;15m- [x] basdfasdfasdfasdf\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[7.303165, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[7.42526, "o", "\u001b[9;13H\u001b[38;5;8m- [x] basdfasdfasdfasdf\u001b[11;13H\u001b[1m\u001b[38;5;15m- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[7.605653, "o", "\u001b[11;13H\u001b[38;5;8m- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[13;13H\u001b[1m\u001b[38;5;15m- [ ] something\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[7.861055, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[8.008956, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[8.262789, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[8.445994, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[8.699737, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[8.9533, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[9.045631, "o", "\u001b[13;16H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[9.299403, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[9.553163, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[9.735068, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[9.988954, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[10.242337, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[10.486221, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[10.741395, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[10.815189, "o", "\u001b[37;1H: \u001b[37;5H \u001b[37;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[10.917172, "o", "\u001b[37;2He\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[11.085181, "o", "\u001b[37;3Hd\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[11.1735, "o", "\u001b[37;4Hi\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[11.279168, "o", "\u001b[37;5Ht\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[11.369147, "o", "\u001b[1;10H~\u001b[1;12Hedit\u001b[1;17Hitem\u001b[3;1H\u001b[38;5;8mpath: kjuulh.other.other.other.something \u001b[4;1H \u001b[5;1H\u001b[39m┌title──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[11.369227, "o", "────────────────────────┐\u001b[6;1H│something\u001b[38;5;0m\u001b[48;5;5m \u001b[6;209H\u001b[39m\u001b[49m│\u001b[7;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[8;1H\u001b[38;5;8m┌description────────────────────────────────────────────────────────────────────────────"] +[11.369285, "o", "────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐\u001b[9;1H│ \u001b[9;15H \u001b[9;19H │\u001b[10;1H└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[11.369321, "o", "───────────────────────────────────────────────────────────────────┘\u001b[11;13H\u001b[39m \u001b[13;13H \u001b[15;9H \u001b[17;9H \u001b[19;13H \u001b[21;17H \u001b[23;17H \u001b[25;9H \u001b[27;1H \u001b[29;1H \u001b[31;5H \u001b[33;5H \u001b[35;1H \u001b[37;1H -- EDIT\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[11.622591, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[11.876231, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[12.129645, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[12.382542, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[12.636292, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[12.705196, "o", "\u001b[6;11Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[12.958571, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[13.10767, "o", "\u001b[6;11H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[13.274155, "o", "\u001b[6;10H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[13.437362, "o", "\u001b[6;9H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[13.603346, "o", "\u001b[6;8H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[13.797662, "o", "\u001b[6;7H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[13.964183, "o", "\u001b[6;6H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[14.128346, "o", "\u001b[6;5H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[14.277769, "o", "\u001b[6;4H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[14.444215, "o", "\u001b[6;3H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[14.607996, "o", "\u001b[6;2H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[14.817381, "o", "\u001b[6;2HI\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[14.938407, "o", "\u001b[6;3H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.105005, "o", "\u001b[6;4Hc\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.177103, "o", "\u001b[6;5Ha\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.237734, "o", "\u001b[6;6Hn\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.314055, "o", "\u001b[6;7H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.50905, "o", "\u001b[6;8He\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.688487, "o", "\u001b[6;9Hd\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.778225, "o", "\u001b[6;10Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.884484, "o", "\u001b[6;11Ht\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[15.927584, "o", "\u001b[6;12H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[16.064325, "o", "\u001b[6;13Ht\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[16.137399, "o", "\u001b[6;14Hh\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[16.274067, "o", "\u001b[6;15Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[16.334342, "o", "\u001b[6;16Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[16.544224, "o", "\u001b[6;17H \u001b[37;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[16.784735, "o", "\u001b[5;1H\u001b[38;5;8m┌title──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐\u001b[6;1H│I can edit this │\u001b[7;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[8;1H\u001b[39m┌description───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[16.784907, "o", "─────────────────┐\u001b[9;1H│ │\u001b[10;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[17.039025, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[17.187426, "o", "\u001b[9;2H\u001b[38;5;0m\u001b[48;5;5m \u001b[37;5H\u001b[39m\u001b[49mEDIT\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[17.441615, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[17.696128, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[17.950481, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[17.954099, "o", "\u001b[9;2HA\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.074522, "o", "\u001b[9;3Hn\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.147127, "o", "\u001b[9;4Hd\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.26807, "o", "\u001b[9;5H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.357652, "o", "\u001b[9;6Ht\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.434358, "o", "\u001b[9;7Hh\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.58746, "o", "\u001b[9;8Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.704545, "o", "\u001b[9;9Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[18.884595, "o", "\u001b[9;10H \u001b[37;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[19.137767, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[19.214049, "o", "\u001b[37;1H: \u001b[37;5H \u001b[37;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[19.333851, "o", "\u001b[37;2Hw\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[19.40729, "o", "\u001b[37;3Hq\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[19.545185, "o", "\u001b[1;10H \u001b[1;12H \u001b[1;17H \u001b[3;1H\u001b[38;5;8m- other\u001b[39m \u001b[4;1H \u001b[5;1H \u001b[38;5;8m- other\u001b[39m \u001b[6;1H \u001b[7;1H \u001b[38;5;8m- other\u001b[39m "] +[19.545334, "o", " \u001b[8;1H \u001b[9;1H \u001b[9;6H \u001b[9;13H\u001b[38;5;8m- [x] I can edit this\u001b[9;209H\u001b[39m \u001b[10;1H \u001b[11;13H\u001b[38;5;8m- [x] basdfasdfasdfasdf\u001b[13;13H\u001b[1m\u001b[38;5;15m- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[15;9H\u001b[22m\u001b[38;5;8m- [x] some\u001b[17;9H- something\u001b[19;13H- something-else\u001b[21;17H- [x] another-real-item-man\u001b[23;17H- [x] arealitembaby\u001b[25;9H- [ ] whatever\u001b[27;1H- some\u001b[29;1H- something\u001b[31;5H- else\u001b[33;5H- third\u001b[35;1H- with-something\u001b[37;1H\u001b[39m --\u001b[37;5HVIEW\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[19.799162, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[20.054028, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[20.307998, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[20.561729, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[20.566624, "o", "\u001b[11;13H\u001b[1m\u001b[38;5;15m- [x] basdfasdfasdfasdf\u001b[13;13H\u001b[22m\u001b[38;5;8m- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[20.702313, "o", "\u001b[9;13H\u001b[1m\u001b[38;5;15m- [x] I can edit this\u001b[11;13H\u001b[22m\u001b[38;5;8m- [x] basdfasdfasdfasdf\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[20.908298, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[21.162091, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[21.37516, "o", "\u001b[9;16H\u001b[1m\u001b[38;5;15m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[21.629428, "o", "\u001b[9;16H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[21.88325, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[21.959451, "o", "\u001b[9;16H\u001b[1m\u001b[38;5;15m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[22.155088, "o", "\u001b[9;16H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[22.348094, "o", "\u001b[9;16H\u001b[1m\u001b[38;5;15m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[22.528582, "o", "\u001b[9;16H\u001b[1m\u001b[38;5;15mx\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[22.782211, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[23.035832, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[23.248605, "o", "\u001b[9;13H\u001b[38;5;8m- [x] I can edit this\u001b[11;13H\u001b[1m\u001b[38;5;15m- [x] basdfasdfasdfasdf\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[23.445613, "o", "\u001b[9;13H\u001b[1m\u001b[38;5;15m- [x] I can edit this\u001b[11;13H\u001b[22m\u001b[38;5;8m- [x] basdfasdfasdfasdf\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[23.654844, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[23.908641, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[24.162166, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[24.415538, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[24.669106, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[24.915592, "o", "\u001b[37;1H: \u001b[37;5H \u001b[37;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[25.038078, "o", "\u001b[37;2He\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[25.2292, "o", "\u001b[37;3Hd\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[25.318513, "o", "\u001b[37;4Hi\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[25.455016, "o", "\u001b[37;5Ht\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[25.544807, "o", "\u001b[1;10H~\u001b[1;12Hedit\u001b[1;17Hitem\u001b[3;1H\u001b[38;5;8mpath: kjuulh.other.other.other.I can edit this \u001b[4;1H \u001b[5;1H\u001b[39m┌title──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[25.54489, "o", "────────────────────────┐\u001b[6;1H│I\u001b[6;4Hcan\u001b[6;8Hedit\u001b[6;13Hthis\u001b[38;5;0m\u001b[48;5;5m \u001b[6;209H\u001b[39m\u001b[49m│\u001b[7;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[8;1H\u001b[38;5;8m┌description─────────────────────────────────────────────────────────────────────"] +[25.544988, "o", "───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐\u001b[9;1H│And this │\u001b[10;1H└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[25.545068, "o", "──────────────────────────────────────────────────────────────────────┘\u001b[11;13H\u001b[39m \u001b[13;13H \u001b[15;9H \u001b[17;9H \u001b[19;13H \u001b[21;17H \u001b[23;17H \u001b[25;9H \u001b[27;1H \u001b[29;1H \u001b[31;5H \u001b[33;5H \u001b[35;1H \u001b[37;1H -- EDIT\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[25.799349, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[26.052485, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[26.23418, "o", "\u001b[6;17Hj\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[26.488909, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[26.742022, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[26.94057, "o", "\u001b[6;17H\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[27.117303, "o", "\u001b[6;17H \u001b[37;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[27.370323, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[27.38653, "o", "\u001b[5;1H\u001b[38;5;8m┌title──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐\u001b[6;1H│I can edit this │\u001b[7;1H└──────────────────────────────────────────────────────"] +[27.386567, "o", "─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[8;1H\u001b[39m┌description───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────"] +[27.386677, "o", "─────────────────┐\u001b[9;1H│And this │\u001b[10;1H└───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[27.639588, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[27.717352, "o", "\u001b[9;2H\u001b[38;5;0m\u001b[48;5;5mA\u001b[37;5H\u001b[39m\u001b[49mEDIT\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[27.970564, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[28.223691, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[28.467566, "o", "\u001b[9;2HA\u001b[37;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[28.72076, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[28.874563, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[29.127769, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[29.33782, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[29.534369, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[29.787555, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[29.984355, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[30.134543, "o", "\u001b[9;2H\u001b[38;5;0m\u001b[48;5;5mA\u001b[37;5H\u001b[39m\u001b[49mEDIT\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[30.388285, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[30.478184, "o", "\u001b[9;2HA\u001b[38;5;0m\u001b[48;5;5mn\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[30.658079, "o", "\u001b[9;3Hn\u001b[38;5;0m\u001b[48;5;5md\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[30.795066, "o", "\u001b[9;4Hd\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[30.943548, "o", "\u001b[9;5H \u001b[38;5;0m\u001b[48;5;5mt\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[31.106805, "o", "\u001b[9;6Ht\u001b[38;5;0m\u001b[48;5;5mh\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[31.243172, "o", "\u001b[9;7Hh\u001b[38;5;0m\u001b[48;5;5mi\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[31.394761, "o", "\u001b[9;8Hi\u001b[38;5;0m\u001b[48;5;5ms\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[31.543508, "o", "\u001b[9;9Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[31.797651, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[31.814543, "o", "\u001b[9;10H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.067544, "o", "\u001b[9;11HI\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.113144, "o", "\u001b[9;12H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.365934, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.397063, "o", "\u001b[9;13Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.650068, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.713855, "o", "\u001b[9;14Hh\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[32.877214, "o", "\u001b[9;15Ho\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.026953, "o", "\u001b[9;16Hu\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.193541, "o", "\u001b[9;17Hl\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.270848, "o", "\u001b[9;18Hd\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.327636, "o", "\u001b[9;19H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.433825, "o", "\u001b[9;20Hg\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.567382, "o", "\u001b[9;21He\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.643795, "o", "\u001b[9;22Ht\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.687125, "o", "\u001b[9;23H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[33.940622, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.064137, "o", "\u001b[9;24Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.167239, "o", "\u001b[9;25Ho\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.227022, "o", "\u001b[9;26Hr\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.423997, "o", "\u001b[9;27Ht\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.514008, "o", "\u001b[9;28Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.677124, "o", "\u001b[9;29Hn\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.707248, "o", "\u001b[9;30Hg\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[34.843905, "o", "\u001b[9;31H \u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[35.007343, "o", "\u001b[9;32Hf\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[35.097998, "o", "\u001b[9;33Hi\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[35.234791, "o", "\u001b[9;34Hx\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[35.398271, "o", "\u001b[9;35He\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[35.534597, "o", "\u001b[9;36Hs\u001b[38;5;0m\u001b[48;5;5m \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[35.746795, "o", "\u001b[9;37H \u001b[37;5HVIEW\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.000798, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.058291, "o", "\u001b[37;1H: \u001b[37;5H \u001b[37;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.147303, "o", "\u001b[37;2Hw\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.22354, "o", "\u001b[37;3Hq\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.37499, "o", "\u001b[1;10H \u001b[1;12H \u001b[1;17H \u001b[3;1H\u001b[38;5;8m- other\u001b[39m \u001b[4;1H \u001b[5;1H \u001b[38;5;8m- other\u001b[39m \u001b[6;1H \u001b[7;1H \u001b[38;5;8m- other\u001b[39m "] +[36.375133, "o", " \u001b[8;1H \u001b[9;1H \u001b[9;6H \u001b[9;11H \u001b[9;13H\u001b[38;5;8m- [x] I can edit this\u001b[39m \u001b[9;209H \u001b[10;1H \u001b[11;13H\u001b[1m\u001b[38;5;15m- [x] basdfasdfasdfasdf\u001b[13;13H\u001b[22m\u001b[38;5;8m- [x] sdlfkasldjflsdaslkdjfalkjsdfl\u001b[15;9H- [x] some\u001b[17;9H- something\u001b[19;13H- something-else\u001b[21;17H- [x] another-real-item-man\u001b[23;17H- [x] arealitembaby\u001b[25;9H- [ ] whatever\u001b[27;1H- some\u001b[29;1H- something\u001b[31;5H- else\u001b[33;5H- third\u001b[35;1H- with-something\u001b[37;1H\u001b[39m --\u001b[37;5HVIEW\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.62897, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[36.883979, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[37.048337, "o", "\u001b[9;13H\u001b[1m\u001b[38;5;15m- [x] I can edit this\u001b[11;13H\u001b[22m\u001b[38;5;8m- [x] basdfasdfasdfasdf\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[37.301888, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[37.556956, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[37.810594, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[38.064062, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[38.320665, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[38.574308, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[38.828028, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[39.081369, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[39.298179, "o", "\u001b[37;1H: \u001b[37;5H \u001b[37;10H \u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[39.524441, "o", "\u001b[37;2Hq\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[39.68854, "o", "\u001b[37;1H --\u001b[37;5HVIEW\u001b[37;10H--\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[39.942362, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[40.196662, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[40.450474, "o", "\u001b[39m\u001b[49m\u001b[59m\u001b[0m\u001b[?25l"] +[40.691621, "o", "\u001b[?1049l\u001b[?25h"] +[40.693631, "o", "\u001b[1m\u001b[7m%\u001b[27m\u001b[1m\u001b[0m \r \r"] +[40.718274, "o", "\r\u001b[0m\u001b[27m\u001b[24m\u001b[J\r\n\u001b[38;2;255;153;102mhyperlog\u001b[0m \u001b[90mmain\u001b[0m\u001b[38;2;255;153;102m \u001b[0m\u001b[38;2;255;153;102m≡ \u001b[0m\u001b[1;31mrs \u001b[0m\u001b[33m38s\u001b[0m \r\n\u001b[38;2;255;153;102m❯\u001b[0m \u001b[K"] +[40.719012, "o", "\u001b[6 q"] +[40.719517, "o", "\u001b[6 q"] +[40.719593, "o", "\u001b[?2004h"] +[42.251381, "o", "\u001b[?2004l\r\r\n"]