Skip to content

Next input system (#332) draft #357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/bin/edit/draw_editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ fn draw_search(ctx: &mut Context, state: &mut State) {
focus = StateSearchKind::Search;

// If the selection is empty, focus the search input field.
// Otherwise, focus the replace input field, if it exists.
// Otherwise, focus the "replace" input field, if it exists.
if let Some(selection) = doc.buffer.borrow_mut().extract_user_selection(false) {
state.search_needle = String::from_utf8_lossy_owned(selection);
focus = state.wants_search.kind;
Expand Down Expand Up @@ -291,8 +291,9 @@ pub fn draw_goto_menu(ctx: &mut Context, state: &mut State) {
let mut done = false;

if let Some(doc) = state.documents.active_mut() {
ctx.modal_begin("goto", loc(LocId::FileGoto));
ctx.modal_begin("goto-menu", loc(LocId::FileGoto));
{
ctx.scope_begin("goto", 1);
if ctx.editline("goto-line", &mut state.goto_target) {
state.goto_invalid = false;
}
Expand All @@ -304,7 +305,7 @@ pub fn draw_goto_menu(ctx: &mut Context, state: &mut State) {
ctx.attr_intrinsic_size(Size { width: 24, height: 1 });
ctx.steal_focus();

if ctx.consume_shortcut(vk::RETURN) {
if ctx.consume_action("submit", SmolString::new("submit").unwrap()) {
match validate_goto_point(&state.goto_target) {
Ok(point) => {
let mut buf = doc.buffer.borrow_mut();
Expand All @@ -316,6 +317,7 @@ pub fn draw_goto_menu(ctx: &mut Context, state: &mut State) {
}
ctx.needs_rerender();
}
ctx.scope_end();
}
done |= ctx.modal_end();
} else {
Expand Down
6 changes: 5 additions & 1 deletion src/bin/edit/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ fn run() -> apperr::Result<()> {

// sys::init() will switch the terminal to raw mode which prevents the user from pressing Ctrl+C.
// Since the `read_file` call may hang for some reason, we must only call this afterwards.
// `set_modes()` will enable mouse mode which is equally annoying to switch out for users
// `set_modes()` will enable mouse mode which is equally annoying to switch out for users,
// and so we do it afterwards, for similar reasons.
sys::switch_modes()?;

let mut vt_parser = vt::Parser::new();
let mut input_parser = input::Parser::new();
let mut tui = Tui::new()?;

tui.declare_scope("goto", &[("back", vk::ESCAPE), ("submit", vk::RETURN)]);

let _restore = setup_terminal(&mut tui, &mut vt_parser);

state.menubar_color_bg = oklab_blend(
Expand Down Expand Up @@ -139,6 +141,8 @@ fn run() -> apperr::Result<()> {
let input = input_iter.next();
let more = input.is_some();
let mut ctx = tui.create_context(input);
// ctx.precompute_layout(|ctx| draw(ctx, &mut state));
ctx.compute_propagation_path();

draw(&mut ctx, &mut state);

Expand Down
78 changes: 78 additions & 0 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

use std::alloc::Allocator;
use std::cmp::Ordering;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::io::Read;
use std::mem::{self, MaybeUninit};
use std::ops::{Bound, Range, RangeBounds};
Expand Down Expand Up @@ -291,3 +293,79 @@ impl AsciiStringHelpers for str {
p.len() <= s.len() && s[..p.len()].eq_ignore_ascii_case(p)
}
}

pub enum StackStringError {
ContentTooLong,
}

impl Debug for StackStringError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "desirable content is too long to fit in the string.")
}
}

#[derive(Clone, Copy)]
pub struct StackString<const N: usize> {
length: usize,
data: [u8; N],
}

impl<const N: usize> StackString<N> {
pub fn new(src: &str) -> Result<Self, StackStringError> {
let bytes = src.bytes().collect::<Vec<u8>>();
if bytes.len() > N {
return Err(StackStringError::ContentTooLong);
}
let mut data = [0u8; N];
// Horrible mem copy
// TODO: Fix ASAP
unsafe {
let chunk = std::slice::from_raw_parts_mut(data.as_mut_ptr(), bytes.len());
chunk.copy_from_slice(&bytes);
}
Ok(Self { length: bytes.len(), data })
}

pub fn as_str(&self) -> &str {
self.as_ref()
}
}

impl<const N: usize> AsRef<str> for StackString<N> {
fn as_ref(&self) -> &str {
// SAFETY: We constructed the string
unsafe { std::str::from_utf8_unchecked(&self.data[0..self.length]) }
}
}

impl<const N: usize> PartialEq for StackString<N> {
fn eq(&self, other: &Self) -> bool {
self.as_str() == other.as_str()
}

fn ne(&self, other: &Self) -> bool {
self.as_str() != other.as_str()
}
}

impl<const N: usize> Eq for StackString<N> {}

impl<const N: usize> Hash for StackString<N> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.as_str().hash(state);
}
}

impl<const N: usize> Display for StackString<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<str as Display>::fmt(self.as_str(), f)
}
}

impl<const N: usize> Debug for StackString<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<str as Debug>::fmt(self.as_str(), f)
}
}

pub type SmolString = StackString<16>;
Loading