Skip to content

Commit

Permalink
- changed debug formatter internally
Browse files Browse the repository at this point in the history
- added keyboard shortcut for clipboard
- fixed issue with subscription snbt reordering
- added new file button
- added refresh button
- refactored bookmark system
  • Loading branch information
RealRTTV committed Mar 23, 2024
1 parent 3109c5b commit 6b71b7d
Show file tree
Hide file tree
Showing 21 changed files with 1,037 additions and 736 deletions.
22 changes: 12 additions & 10 deletions src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,14 +135,17 @@ pub const LONG_ARRAY_GHOST_UV: Vec2u = Vec2u::new(0, 48);
pub const CHUNK_GHOST_UV: Vec2u = Vec2u::new(64, 48);
pub const ALERT_UV: Vec2u = Vec2u::new(112, 144);
pub const BACKDROP_UV: Vec2u = Vec2u::new(32, 160);
pub const ADD_SEARCH_BOOKMARKS: Vec2u = Vec2u::new(48, 160);
pub const REMOVE_SEARCH_BOOKMARKS: Vec2u = Vec2u::new(64, 160);
pub const SEARCH_KEYS: Vec2u = Vec2u::new(80, 160);
pub const SEARCH_VALUES: Vec2u = Vec2u::new(80, 176);
pub const SEARCH_KEYS_AND_VALUES: Vec2u = Vec2u::new(80, 192);
pub const STRING_SEARCH_MODE: Vec2u = Vec2u::new(96, 160);
pub const REGEX_SEARCH_MODE: Vec2u = Vec2u::new(96, 176);
pub const SNBT_SEARCH_MODE: Vec2u = Vec2u::new(96, 192);
pub const ADD_SEARCH_BOOKMARKS_UV: Vec2u = Vec2u::new(48, 160);
pub const REMOVE_SEARCH_BOOKMARKS_UV: Vec2u = Vec2u::new(64, 160);
pub const SEARCH_KEYS_UV: Vec2u = Vec2u::new(80, 160);
pub const SEARCH_VALUES_UV: Vec2u = Vec2u::new(80, 176);
pub const SEARCH_KEYS_AND_VALUES_UV: Vec2u = Vec2u::new(80, 192);
pub const STRING_SEARCH_MODE_UV: Vec2u = Vec2u::new(96, 160);
pub const REGEX_SEARCH_MODE_UV: Vec2u = Vec2u::new(96, 176);
pub const SNBT_SEARCH_MODE_UV: Vec2u = Vec2u::new(96, 192);
pub const NEW_FILE_UV: Vec2u = Vec2u::new(96, 48);
pub const REFRESH_UV: Vec2u = Vec2u::new(152, 144);
pub const DISABLED_REFRESH_UV: Vec2u = Vec2u::new(168, 144);

pub const BASE_Z: u8 = 5;
pub const JUST_OVERLAPPING_BASE_Z: u8 = BASE_Z + 1;
Expand All @@ -153,10 +156,9 @@ pub const LINE_NUMBER_Z: u8 = 60;
pub const LINE_NUMBER_CONNECTOR_Z: u8 = LINE_NUMBER_Z + 1;
pub const BOOKMARK_Z: u8 = 80;
pub const SELECTED_TEXT_Z: u8 = 130;
pub const ELEMENT_HIGHLIGHT_Z: u8 = SELECTED_TEXT_Z;
pub const ACTION_WHEEL_Z: u8 = 190;
pub const SCROLLBAR_Z: u8 = 200;
pub const SCROLLBAR_BOOKMARK_Z: u8 = SCROLLBAR_Z - 1;
pub const SCROLLBAR_Z: u8 = 200;
pub const HELD_ENTRY_Z: u8 = 210;
pub const ALERT_Z: u8 = 240;
pub const ALERT_TEXT_Z: u8 = ALERT_Z + 1;
Expand Down
Binary file modified src/assets/atlas.hex
Binary file not shown.
Binary file modified src/assets/build/atlas.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
291 changes: 291 additions & 0 deletions src/bookmark.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,291 @@
use std::cmp::Ordering;
use std::collections::Bound;
use std::convert::identity;
use std::ops::{Deref, DerefMut, Index, IndexMut, RangeBounds};
use crate::assets::{BOOKMARK_UV, HIDDEN_BOOKMARK_UV};
use crate::vertex_buffer_builder::Vec2u;

macro_rules! slice {
($($t:tt)*) => {
unsafe { core::mem::transmute::<&[Bookmark], &BookmarkSlice>(&$($t)*) }
};
}

macro_rules! slice_mut {
($($t:tt)*) => {
unsafe { core::mem::transmute::<&mut [Bookmark], &mut BookmarkSlice>(&mut $($t)*) }
};
}

#[derive(Copy, Clone, Debug)]
pub struct Bookmark {
true_line_number: usize,
line_number: usize,
uv: Vec2u,
}

impl Bookmark {
#[inline]
pub const fn new(true_line_number: usize, line_number: usize) -> Self {
Self {
true_line_number,
line_number,
uv: BOOKMARK_UV,
}
}

#[inline]
pub const fn with_uv(true_line_number: usize, line_number: usize, uv: Vec2u) -> Self {
Self {
true_line_number,
line_number,
uv,
}
}

#[inline]
pub const fn true_line_number(self) -> usize { self.true_line_number }

#[inline]
pub const fn line_number(self) -> usize { self.line_number }

#[inline]
pub const fn uv(self) -> Vec2u { self.uv }

#[inline]
pub const fn hidden(self, line_number: usize) -> Self {
Self {
true_line_number: self.true_line_number,
line_number,
uv: HIDDEN_BOOKMARK_UV,
}
}

#[inline]
pub const fn open(self, line_number: usize) -> Self {
Self {
true_line_number: self.true_line_number,
line_number,
uv: BOOKMARK_UV,
}
}

#[inline]
pub const fn offset(self, offset: usize, true_offset: usize) -> Self {
Self {
true_line_number: self.true_line_number.wrapping_add(true_offset),
line_number: self.line_number.wrapping_add(offset),
uv: self.uv,
}
}
}

impl PartialEq for Bookmark {
fn eq(&self, other: &Self) -> bool { self.true_line_number == other.true_line_number }
}

impl Eq for Bookmark {}

impl PartialOrd<Self> for Bookmark {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { Some(self.cmp(other)) }
}
impl Ord for Bookmark {
fn cmp(&self, other: &Self) -> Ordering { self.true_line_number.cmp(&other.true_line_number) }
}

pub struct Bookmarks {
inner: Vec<Bookmark>,
}

impl Bookmarks {
#[inline]
pub const fn new() -> Self {
Self {
inner: vec![]
}
}

#[inline]
pub fn toggle(&mut self, bookmark: Bookmark) -> Result<(), Bookmark> {
match self.inner.binary_search(&bookmark) {
Ok(idx) => Err(self.inner.remove(idx)),
Err(idx) => {
self.inner.insert(idx, bookmark);
Ok(())
}
}
}

#[inline]
pub fn clear(&mut self) {
self.inner.clear();
}

/// # Safety
/// `inner` must be sorted least to greatest, i.e. it is up to the caller to assure `inner.is_sorted()`
#[inline]
pub unsafe fn from_raw(inner: Vec<Bookmark>) -> Self {
Self {
inner
}
}

#[inline]
pub fn into_raw(self) -> Box<[Bookmark]> {
self.inner.into_boxed_slice()
}

#[inline]
pub fn remove<R: RangeBounds<usize>>(&mut self, range: R) -> Vec<Bookmark> {
match (range.start_bound().map(|&x| Bookmark::new(x, 0)), range.end_bound().map(|&x| Bookmark::new(x, 0))) {
(Bound::Unbounded, Bound::Unbounded) => self.inner.drain(..),
(Bound::Unbounded, Bound::Included(ref end)) => self.inner.drain(..=self.binary_search(end).unwrap_or_else(identity)),
(Bound::Unbounded, Bound::Excluded(ref end)) => self.inner.drain(..self.binary_search(end).unwrap_or_else(identity)),
(Bound::Included(ref start), Bound::Unbounded) => self.inner.drain(self.binary_search(start).unwrap_or_else(identity)..),
(Bound::Included(ref start), Bound::Included(ref end)) => self.inner.drain(self.binary_search(start).unwrap_or_else(identity)..=self.binary_search(end).unwrap_or_else(identity)),
(Bound::Included(ref start), Bound::Excluded(ref end)) => self.inner.drain(self.binary_search(start).unwrap_or_else(identity)..self.binary_search(end).unwrap_or_else(identity)),
(Bound::Excluded(ref start), Bound::Unbounded) => self.inner.drain(self.binary_search(start).map_or_else(identity, |x| x + 1)..),
(Bound::Excluded(ref start), Bound::Included(ref end)) => self.inner.drain(self.binary_search(start).map_or_else(identity, |x| x + 1)..=self.binary_search(end).unwrap_or_else(identity)),
(Bound::Excluded(ref start), Bound::Excluded(ref end)) => self.inner.drain(self.binary_search(start).map_or_else(identity, |x| x + 1)..self.binary_search(end).unwrap_or_else(identity)),
}.collect()
}
}

#[repr(transparent)]
pub struct BookmarkSlice([Bookmark]);

impl BookmarkSlice {
pub const EMPTY: &'static BookmarkSlice = unsafe { core::mem::transmute::<&[Bookmark], &Self>(&[]) };
pub const EMPTY_MUT: &'static mut BookmarkSlice = unsafe { core::mem::transmute::<&mut [Bookmark], &mut Self>(&mut []) };

#[inline]
pub fn increment(&mut self, value: usize, true_value: usize) {
for bookmark in &mut self.0 {
bookmark.line_number = bookmark.line_number.wrapping_add(value);
bookmark.true_line_number = bookmark.true_line_number.wrapping_add(true_value);
}
}

#[inline]
pub fn decrement(&mut self, value: usize, true_value: usize) {
for bookmark in &mut self.0 {
bookmark.line_number -= value;
bookmark.true_line_number -= true_value;
}
}

#[inline]
pub fn split_first(&self) -> Option<(Bookmark, &BookmarkSlice)> {
if let [head, rest @ ..] = &self.0 {
Some((*head, slice!(rest)))
} else {
None
}
}

#[inline]
pub fn iter(&self) -> Iter<'_> {
Iter(&self.0)
}

#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_> {
IterMut(&mut self.0)
}
}

impl Deref for Bookmarks {
type Target = BookmarkSlice;

fn deref(&self) -> &Self::Target {
unsafe { core::mem::transmute(self.inner.as_slice()) }
}
}

impl DerefMut for Bookmarks {
fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { core::mem::transmute(self.inner.as_mut_slice()) }
}
}

impl Deref for BookmarkSlice {
type Target = [Bookmark];

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for BookmarkSlice {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

pub struct Iter<'a>(&'a [Bookmark]);

impl<'a> Iterator for Iter<'a> {
type Item = Bookmark;

fn next(&mut self) -> Option<Self::Item> {
if let Some((&item, rest)) = self.0.split_first() {
self.0 = rest;
Some(item)
} else {
None
}
}
}

pub struct IterMut<'a>(&'a mut [Bookmark]);

impl<'a> Iterator for IterMut<'a> {
type Item = &'a mut Bookmark;

fn next(&mut self) -> Option<Self::Item> {
if self.0.is_empty() {
None
} else {
unsafe {
let ptr = self.0.as_mut_ptr();
let len = self.0.len();
self.0 = core::slice::from_raw_parts_mut(ptr.add(1), len - 1);
Some(core::mem::transmute(ptr))
}
}
}
}

impl<R: RangeBounds<usize>> Index<R> for BookmarkSlice {
type Output = BookmarkSlice;

fn index(&self, index: R) -> &Self::Output {
match (index.start_bound().map(|&x| Bookmark::new(x, 0)), index.end_bound().map(|&x| Bookmark::new(x, 0))) {
(Bound::Unbounded, Bound::Unbounded) => self,
(Bound::Unbounded, Bound::Included(ref end)) => { let end = self.binary_search(end).unwrap_or_else(identity); if end >= self.len() { BookmarkSlice::EMPTY } else { slice!(self.0[..=end]) } },
(Bound::Unbounded, Bound::Excluded(ref end)) => { let end = self.binary_search(end).unwrap_or_else(identity); slice!(self.0[..end]) },
(Bound::Included(ref start), Bound::Unbounded) => { let start = self.binary_search(start).unwrap_or_else(identity); slice!(self.0[start..]) },
(Bound::Included(ref start), Bound::Included(ref end)) => { let start = self.binary_search(start).unwrap_or_else(identity); let end = self.binary_search(end).unwrap_or_else(identity); if end >= self.len() { BookmarkSlice::EMPTY } else { slice!(self.0[start..=end]) } },
(Bound::Included(ref start), Bound::Excluded(ref end)) => { let start = self.binary_search(start).unwrap_or_else(identity); let end = self.binary_search(end).unwrap_or_else(identity); slice!(self.0[start..end]) },
(Bound::Excluded(ref start), Bound::Unbounded) => { let start = self.binary_search(start).map_or_else(identity, |x| x + 1); slice!(self.0[start..]) },
(Bound::Excluded(ref start), Bound::Included(ref end)) => { let start = self.binary_search(start).map_or_else(identity, |x| x + 1); let end = self.binary_search(end).unwrap_or_else(identity); if end >= self.len() { BookmarkSlice::EMPTY } else { slice!(self.0[start..=end]) } },
(Bound::Excluded(ref start), Bound::Excluded(ref end)) => { let start = self.binary_search(start).map_or_else(identity, |x| x + 1); let end = self.binary_search(end).unwrap_or_else(identity); slice!(self.0[start..end]) },
}
}
}

impl<R: RangeBounds<usize>> IndexMut<R> for BookmarkSlice {
fn index_mut(&mut self, index: R) -> &mut Self::Output {
match (index.start_bound().map(|&x| Bookmark::new(x, 0)), index.end_bound().map(|&x| Bookmark::new(x, 0))) {
(Bound::Unbounded, Bound::Unbounded) => self,
(Bound::Unbounded, Bound::Included(ref end)) => { let end = self.binary_search(end).unwrap_or_else(identity); if end >= self.len() { BookmarkSlice::EMPTY_MUT } else { slice_mut!(self.0[..=end]) } },
(Bound::Unbounded, Bound::Excluded(ref end)) => { let end = self.binary_search(end).unwrap_or_else(identity); slice_mut!(self.0[..end]) },
(Bound::Included(ref start), Bound::Unbounded) => { let start = self.binary_search(start).unwrap_or_else(identity); slice_mut!(self.0[start..]) },
(Bound::Included(ref start), Bound::Included(ref end)) => { let start = self.binary_search(start).unwrap_or_else(identity); let end = self.binary_search(end).unwrap_or_else(identity); if end >= self.len() { BookmarkSlice::EMPTY_MUT } else { slice_mut!(self.0[start..=end]) } },
(Bound::Included(ref start), Bound::Excluded(ref end)) => { let start = self.binary_search(start).unwrap_or_else(identity); let end = self.binary_search(end).unwrap_or_else(identity); slice_mut!(self.0[start..end]) },
(Bound::Excluded(ref start), Bound::Unbounded) => { let start = self.binary_search(start).map_or_else(identity, |x| x + 1); slice_mut!(self.0[start..]) },
(Bound::Excluded(ref start), Bound::Included(ref end)) => { let start = self.binary_search(start).map_or_else(identity, |x| x + 1); let end = self.binary_search(end).unwrap_or_else(identity); if end >= self.len() { BookmarkSlice::EMPTY_MUT } else { slice_mut!(self.0[start..=end]) } },
(Bound::Excluded(ref start), Bound::Excluded(ref end)) => { let start = self.binary_search(start).map_or_else(identity, |x| x + 1); let end = self.binary_search(end).unwrap_or_else(identity); slice_mut!(self.0[start..end]) },
}
}
}
2 changes: 1 addition & 1 deletion src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ pub fn find() -> ! {
if !bookmarks.is_empty() {
Some(SearchResult {
path,
lines: bookmarks.into_iter().map(|x| x.true_line_number).collect(),
lines: bookmarks.into_iter().map(|x| x.true_line_number()).collect(),
})
} else {
None
Expand Down
18 changes: 6 additions & 12 deletions src/element_action.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use std::cmp::Ordering;
use std::convert::identity;
#[cfg(not(target_arch = "wasm32"))]
use std::fs::OpenOptions;
#[cfg(not(target_arch = "wasm32"))]
use std::process::Command;
use std::{fs::OpenOptions, process::Command};

use compact_str::CompactString;
#[cfg(not(target_arch = "wasm32"))]
use notify::{EventKind, PollWatcher, RecursiveMode, Watcher};
use uuid::Uuid;

use crate::{Bookmark, panic_unchecked, set_clipboard, FileUpdateSubscription, since_epoch};
use crate::{panic_unchecked, set_clipboard, FileUpdateSubscription, since_epoch};
#[cfg(not(target_arch = "wasm32"))]
use crate::{FileUpdateSubscriptionType, assets::{OPEN_ARRAY_IN_HEX_UV, OPEN_IN_TXT}};
use crate::assets::{ACTION_WHEEL_Z, COPY_FORMATTED_UV, COPY_RAW_UV, SORT_COMPOUND_BY_NAME, SORT_COMPOUND_BY_TYPE};
Expand All @@ -21,6 +18,7 @@ use crate::elements::list::NbtList;
use crate::elements::string::NbtString;
use crate::vertex_buffer_builder::VertexBufferBuilder;
use crate::workbench_action::WorkbenchAction;
use crate::bookmark::Bookmarks;

#[derive(Copy, Clone)]
pub enum ElementAction {
Expand Down Expand Up @@ -112,7 +110,7 @@ impl ElementAction {
}

#[allow(clippy::too_many_lines)]
pub fn apply(self, key: Option<CompactString>, indices: Box<[usize]>, tab_uuid: Uuid, true_line_number: usize, line_number: usize, element: &mut NbtElement, bookmarks: &mut Vec<Bookmark>, subscription: &mut Option<FileUpdateSubscription>) -> Option<WorkbenchAction> {
pub fn apply(self, key: Option<CompactString>, indices: Box<[usize]>, tab_uuid: Uuid, true_line_number: usize, line_number: usize, element: &mut NbtElement, bookmarks: &mut Bookmarks, subscription: &mut Option<FileUpdateSubscription>) -> Option<WorkbenchAction> {
#[must_use]
#[cfg(not(target_arch = "wasm32"))]
fn open_file(str: &str) -> bool {
Expand Down Expand Up @@ -271,9 +269,7 @@ impl ElementAction {
Self::SortCompoundByName => {
let open = element.open();
let true_height = element.true_height();
let bookmark_start = bookmarks.binary_search(&Bookmark::new(true_line_number, 0)).map_or_else(identity, |x| x + 1);
let bookmark_end = bookmarks.binary_search(&Bookmark::new(true_line_number + element.true_height() - 1, 0)).map_or_else(identity, |x| x + 1);
let bookmark_slice = if bookmark_end > bookmark_start || bookmark_end > bookmarks.len() { &mut [] } else { &mut bookmarks[bookmark_start..bookmark_end] };
let bookmark_slice = &mut bookmarks[true_line_number..true_line_number + element.true_height()];
let reordering_indices = if let Some(compound) = element.as_compound_mut() {
compound.entries.sort_by(Self::by_name, line_number, true_line_number, true_height, open, bookmark_slice)
} else if let Some(chunk) = element.as_chunk_mut() {
Expand All @@ -287,9 +283,7 @@ impl ElementAction {
Self::SortCompoundByType => {
let open = element.open();
let true_height = element.true_height();
let bookmark_start = bookmarks.binary_search(&Bookmark::new(true_line_number, 0)).map_or_else(identity, |x| x + 1);
let bookmark_end = bookmarks.binary_search(&Bookmark::new(true_line_number + element.true_height() - 1, 0)).map_or_else(identity, |x| x + 1);
let bookmark_slice = if bookmark_end < bookmark_start || bookmark_end > bookmarks.len() { &mut [] } else { &mut bookmarks[bookmark_start..bookmark_end] };
let bookmark_slice = &mut bookmarks[true_line_number..true_line_number + element.true_height()];
let reordering_indices = if let Some(compound) = element.as_compound_mut() {
compound.entries.sort_by(Self::by_type, line_number, true_line_number, true_height, open, bookmark_slice)
} else if let Some(chunk) = element.as_chunk_mut() {
Expand Down
Loading

0 comments on commit 6b71b7d

Please sign in to comment.