it fucken works!!
This commit is contained in:
parent
d7fe624e8b
commit
4382205e84
13 changed files with 413 additions and 51 deletions
116
Cargo.lock
generated
116
Cargo.lock
generated
|
@ -306,12 +306,27 @@ dependencies = [
|
|||
"rustc-demangle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.21.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.5.3"
|
||||
|
@ -1834,6 +1849,18 @@ dependencies = [
|
|||
"vcpkg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "line-wrap"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
|
||||
|
||||
[[package]]
|
||||
name = "linkme"
|
||||
version = "0.3.26"
|
||||
|
@ -1998,6 +2025,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"slotmap",
|
||||
"smallvec",
|
||||
"smol",
|
||||
"taffy",
|
||||
"thiserror",
|
||||
"time",
|
||||
|
@ -2105,7 +2133,9 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"funnylog",
|
||||
"log",
|
||||
"ming",
|
||||
"syntect",
|
||||
"widestring",
|
||||
]
|
||||
|
||||
|
@ -2294,6 +2324,28 @@ version = "1.19.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "onig"
|
||||
version = "6.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c4b31c8722ad9171c6d77d3557db078cab2bd50afcc9d09c8b315c59df8ca4f"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"onig_sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "onig_sys"
|
||||
version = "69.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b829e3d7e9cc74c7e315ee8edb185bf4190da5acde74afd7fc59c35b1f086e7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "oo7"
|
||||
version = "0.3.2"
|
||||
|
@ -2502,6 +2554,20 @@ version = "0.3.30"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
|
||||
|
||||
[[package]]
|
||||
name = "plist"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"indexmap",
|
||||
"line-wrap",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.16.8"
|
||||
|
@ -3164,6 +3230,23 @@ dependencies = [
|
|||
"wayland-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smol"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e635339259e51ef85ac7aa29a1cd991b957047507288697a690e80ab97d07cad"
|
||||
dependencies = [
|
||||
"async-channel 2.3.0",
|
||||
"async-executor",
|
||||
"async-fs",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-net",
|
||||
"async-process",
|
||||
"blocking",
|
||||
"futures-lite 2.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.7"
|
||||
|
@ -3269,6 +3352,28 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syntect"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags 1.3.2",
|
||||
"flate2",
|
||||
"fnv",
|
||||
"once_cell",
|
||||
"onig",
|
||||
"plist",
|
||||
"regex-syntax",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"walkdir",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-locale"
|
||||
version = "0.3.1"
|
||||
|
@ -3654,7 +3759,7 @@ version = "0.41.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c704361d822337cfc00387672c7b59eaa72a1f0744f62b2a68aa228a0c6927d"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"base64 0.22.1",
|
||||
"data-url",
|
||||
"flate2",
|
||||
"imagesize",
|
||||
|
@ -4180,6 +4285,15 @@ version = "0.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "yazi"
|
||||
version = "0.1.6"
|
||||
|
|
|
@ -8,6 +8,8 @@ funnylog.workspace = true
|
|||
ming.workspace = true
|
||||
anyhow.workspace = true
|
||||
widestring = "1.1.0"
|
||||
syntect = "5.2.0"
|
||||
log.workspace = true
|
||||
|
||||
[workspace]
|
||||
members = [
|
||||
|
|
|
@ -61,6 +61,7 @@ time.workspace = true
|
|||
util.workspace = true
|
||||
uuid.workspace = true
|
||||
waker-fn = "1.1.0"
|
||||
smol = "2.0.0"
|
||||
|
||||
[dev-dependencies]
|
||||
backtrace = "0.3"
|
||||
|
|
|
@ -143,7 +143,13 @@ impl StyledText {
|
|||
}
|
||||
}
|
||||
|
||||
/// todo!()
|
||||
/// Get a reference to the text inside this [`StyledText`]
|
||||
pub fn text(&self) -> &str {
|
||||
&self.text
|
||||
}
|
||||
|
||||
/// Access the text layout.
|
||||
/// This method is not intended to be used outside ming.
|
||||
pub fn layout(&self) -> &TextLayout {
|
||||
&self.layout
|
||||
}
|
||||
|
|
|
@ -9,13 +9,9 @@ use util::arc_cow::ArcCow;
|
|||
pub struct SharedString(ArcCow<'static, str>);
|
||||
|
||||
impl SharedString {
|
||||
/// Create a new shared string from anything that can be turned into an [`ArcCow`], including:
|
||||
/// - `&'static `[`str`]
|
||||
/// - [`String`]
|
||||
/// - [`Arc`]`<`[`str`]`>`
|
||||
/// - a reference to any of the above
|
||||
pub fn new(ac: impl Into<ArcCow<'static, str>>) -> Self {
|
||||
Self(ac.into())
|
||||
/// Create a new empty [`SharedString`].
|
||||
pub fn new() -> Self {
|
||||
Self(ArcCow::Borrowed(""))
|
||||
}
|
||||
|
||||
/// Create a new shared string from a `&'static `[`str`].
|
||||
|
|
|
@ -102,7 +102,7 @@ impl<T: 'static> futures::Stream for Observation<T> {
|
|||
|
||||
/// observe returns a stream of the change events from the given `View` or `Model`
|
||||
pub fn observe<T: 'static>(entity: &impl Entity<T>, cx: &mut TestAppContext) -> Observation<()> {
|
||||
let (tx, rx) = smol::channel::unbounded();
|
||||
let (tx, rx) = channel::unbounded();
|
||||
let _subscription = cx.update(|cx| {
|
||||
cx.observe(entity, move |_, _| {
|
||||
let _ = smol::block_on(tx.send(()));
|
||||
|
|
|
@ -2,10 +2,7 @@
|
|||
use std::time::Duration;
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
use futures::Future;
|
||||
|
||||
#[cfg(any(test, feature = "test-support"))]
|
||||
use smol::future::FutureExt;
|
||||
use futures::{Future, FutureExt};
|
||||
|
||||
pub use util::*;
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
|
||||
scripts = {
|
||||
fmt.exec = "${config.treefmt.build.wrapper}/bin/treefmt .";
|
||||
nite.exec = "RUST_LOG=info,nite=trace,ming=trace cargo run";
|
||||
nite.exec = "RUST_LOG=info,nite=trace,ming=trace cargo run -- $@";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
use std::{ops::Range, path::PathBuf};
|
||||
use syntect::{
|
||||
highlighting::{
|
||||
Color, FontStyle as SFontStyle, HighlightState, Highlighter, RangedHighlightIterator, Theme,
|
||||
},
|
||||
parsing::{ParseState, ScopeStack, SyntaxSet},
|
||||
};
|
||||
use widestring::Utf16String;
|
||||
|
||||
use super::*;
|
||||
|
@ -6,18 +12,19 @@ use super::*;
|
|||
pub struct Buffer {
|
||||
pub text: Utf16String,
|
||||
pub path: Option<PathBuf>,
|
||||
pub marked: Option<Range<usize>>
|
||||
pub marked: Option<Range<usize>>,
|
||||
pub selected: Option<Range<usize>>,
|
||||
}
|
||||
|
||||
impl Buffer {
|
||||
pub fn make_scratch<V>(cx: &mut ViewContext<V>) -> Model<Self> {
|
||||
cx.new_model(|_cx| Self::scratch())
|
||||
}
|
||||
|
||||
pub fn read(path: PathBuf) -> anyhow::Result<Self> {
|
||||
let text = std::fs::read_to_string(&path)?;
|
||||
log::trace!("read file: {text}");
|
||||
Ok(Self {
|
||||
text: std::fs::read_to_string(&path)?,
|
||||
text: text.into(),
|
||||
path: Some(path),
|
||||
marked: None,
|
||||
selected: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -25,6 +32,81 @@ impl Buffer {
|
|||
Self {
|
||||
text: Utf16String::new(),
|
||||
path: None,
|
||||
marked: None,
|
||||
selected: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn styled(
|
||||
&self,
|
||||
default_style: &TextStyle,
|
||||
theme: &Theme,
|
||||
syntax_set: &SyntaxSet,
|
||||
scrolled: usize,
|
||||
) -> Vec<StyledText> {
|
||||
let text = self.text.to_string();
|
||||
|
||||
if let Some(syntax) = self
|
||||
.path
|
||||
.as_ref()
|
||||
.and_then(|path| path.extension())
|
||||
.and_then(|extension| {
|
||||
syntax_set.find_syntax_by_extension(extension.to_str().expect("non-utf8 file ext"))
|
||||
})
|
||||
{
|
||||
let mut parse = ParseState::new(syntax);
|
||||
let hler = Highlighter::new(theme);
|
||||
let mut hl = HighlightState::new(&hler, ScopeStack::new());
|
||||
|
||||
text.lines()
|
||||
.skip(scrolled)
|
||||
.flat_map(|line| {
|
||||
parse.parse_line(line, &syntax_set).map(|parsed| {
|
||||
StyledText::new(Arc::from(line)).with_highlights(
|
||||
default_style,
|
||||
RangedHighlightIterator::new(&mut hl, &parsed, line, &hler).map(
|
||||
move |(style, _text, range)| {
|
||||
(
|
||||
range,
|
||||
HighlightStyle {
|
||||
color: Some(hsla_from_syntect(style.foreground)),
|
||||
background_color: None,
|
||||
font_style: style
|
||||
.font_style
|
||||
.contains(SFontStyle::ITALIC)
|
||||
.then(|| FontStyle::Italic),
|
||||
underline: style
|
||||
.font_style
|
||||
.contains(SFontStyle::UNDERLINE)
|
||||
.then(|| UnderlineStyle::default()),
|
||||
font_weight: style
|
||||
.font_style
|
||||
.contains(SFontStyle::BOLD)
|
||||
.then(|| FontWeight::BOLD),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
},
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
text.lines()
|
||||
.skip(scrolled)
|
||||
.map(|line| StyledText::new(Arc::from(line)))
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hsla_from_syntect(color: Color) -> Hsla {
|
||||
Rgba {
|
||||
r: color.r as f32 / 255.0,
|
||||
g: color.g as f32 / 255.0,
|
||||
b: color.b as f32 / 255.0,
|
||||
a: color.a as f32 / 255.0,
|
||||
}
|
||||
.into()
|
||||
}
|
||||
|
|
|
@ -1,25 +1,68 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
use syntect::{highlighting::ThemeSet, parsing::SyntaxSet};
|
||||
|
||||
use super::*;
|
||||
|
||||
mod element;
|
||||
mod input;
|
||||
|
||||
pub struct EditorSettings {
|
||||
theme_set: ThemeSet,
|
||||
syntax_set: SyntaxSet,
|
||||
}
|
||||
|
||||
impl EditorSettings {
|
||||
pub fn load_defaults() -> Self {
|
||||
Self {
|
||||
theme_set: ThemeSet::load_defaults(),
|
||||
syntax_set: SyntaxSet::load_defaults_nonewlines(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Editor {
|
||||
focus_handle: FocusHandle,
|
||||
buf: Model<crate::buffer::Buffer>
|
||||
buf: Model<crate::buffer::Buffer>,
|
||||
settings: Model<EditorSettings>,
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
pub fn make<V: 'static>(cx: &mut ViewContext<V>) -> View<Self> {
|
||||
pub fn make<V: 'static>(
|
||||
cx: &mut ViewContext<V>,
|
||||
settings: Model<EditorSettings>,
|
||||
) -> View<Self> {
|
||||
cx.new_view(|cx| Self {
|
||||
buf: crate::buffer::Buffer::make_scratch(cx),
|
||||
focus_handle: cx.focus_handle()
|
||||
buf: cx.new_model(|_cx| {
|
||||
if let Some(path) = std::env::args().skip(1).next() {
|
||||
crate::buffer::Buffer::read(PathBuf::from(path)).expect("file failed to read")
|
||||
} else {
|
||||
crate::buffer::Buffer::scratch()
|
||||
}
|
||||
}),
|
||||
focus_handle: cx.focus_handle(),
|
||||
settings,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Editor {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
element::EditorElement::new(cx.view())
|
||||
element::EditorElement::new(
|
||||
cx.view(),
|
||||
element::EditorStyle {
|
||||
font_size: AbsoluteLength::Pixels(px(14.0)),
|
||||
font_family: SharedString::from_static("ComicShannsMono Nerd Font Mono"),
|
||||
hl_theme: self
|
||||
.settings
|
||||
.read(cx)
|
||||
.theme_set
|
||||
.themes
|
||||
.get("base16-mocha.dark")
|
||||
.expect("mocha.dark wasn't available even if it's told it's there")
|
||||
.clone(),
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
use std::{cell::Cell, rc::Rc};
|
||||
|
||||
use syntect::highlighting::Theme;
|
||||
|
||||
use self::buffer::hsla_from_syntect;
|
||||
|
||||
use super::*;
|
||||
|
||||
pub struct EditorStyle {
|
||||
pub font_family: SharedString,
|
||||
pub font_size: AbsoluteLength,
|
||||
}
|
||||
|
||||
impl Default for EditorStyle {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
font_family: SharedString::from_static("Monospace"),
|
||||
font_size: AbsoluteLength::Pixels(px(14)),
|
||||
}
|
||||
}
|
||||
pub hl_theme: Theme,
|
||||
}
|
||||
|
||||
pub struct EditorElement {
|
||||
editor: View<Editor>,
|
||||
style: EditorStyle,
|
||||
scrolled: Rc<Cell<usize>>,
|
||||
}
|
||||
|
||||
impl EditorElement {
|
||||
pub fn new(viewref: &View<Editor>) -> Self {
|
||||
pub fn new(viewref: &View<Editor>, style: EditorStyle) -> Self {
|
||||
Self {
|
||||
editor: viewref.clone(),
|
||||
style: EditorStyle::default(),
|
||||
style,
|
||||
scrolled: Rc::new(Cell::new(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,10 +36,13 @@ impl IntoElement for EditorElement {
|
|||
}
|
||||
}
|
||||
|
||||
struct EditorLayout {}
|
||||
pub struct EditorLayout {}
|
||||
pub struct EditorRequestLayout {
|
||||
styled: Vec<(LayoutId, StyledText, Bounds<Pixels>)>,
|
||||
}
|
||||
|
||||
impl Element for EditorElement {
|
||||
type RequestLayoutState = ();
|
||||
type RequestLayoutState = EditorRequestLayout;
|
||||
type PrepaintState = EditorLayout;
|
||||
|
||||
fn id(&self) -> Option<ElementId> {
|
||||
|
@ -51,6 +54,41 @@ impl Element for EditorElement {
|
|||
id: Option<&GlobalElementId>,
|
||||
cx: &mut WindowContext,
|
||||
) -> (LayoutId, Self::RequestLayoutState) {
|
||||
let editor = self.editor.read(cx);
|
||||
let mut styled = editor.buf.read(cx).styled(
|
||||
&TextStyle {
|
||||
font_size: self.style.font_size,
|
||||
font_family: self.style.font_family.clone(),
|
||||
..Default::default()
|
||||
},
|
||||
&self.style.hl_theme,
|
||||
&editor.settings.read(cx).syntax_set,
|
||||
self.scrolled.get(),
|
||||
);
|
||||
|
||||
let children = styled
|
||||
.iter_mut()
|
||||
.map(|styled| styled.request_layout(None, cx).0)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
(
|
||||
cx.request_layout(
|
||||
Style {
|
||||
display: Display::Flex,
|
||||
flex_direction: FlexDirection::Column,
|
||||
align_content: Some(AlignContent::FlexStart),
|
||||
..Default::default()
|
||||
},
|
||||
children.iter().copied(),
|
||||
),
|
||||
EditorRequestLayout {
|
||||
styled: children
|
||||
.into_iter()
|
||||
.zip(styled)
|
||||
.map(|(id, styled)| (id, styled, Bounds::default()))
|
||||
.collect(),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn prepaint(
|
||||
|
@ -60,6 +98,14 @@ impl Element for EditorElement {
|
|||
request_layout: &mut Self::RequestLayoutState,
|
||||
cx: &mut WindowContext,
|
||||
) -> Self::PrepaintState {
|
||||
request_layout
|
||||
.styled
|
||||
.iter_mut()
|
||||
.for_each(|(id, styled, bounds)| {
|
||||
*bounds = cx.layout_bounds(*id);
|
||||
styled.prepaint(None, *bounds, &mut (), cx)
|
||||
});
|
||||
|
||||
EditorLayout {}
|
||||
}
|
||||
|
||||
|
@ -80,14 +126,44 @@ impl Element for EditorElement {
|
|||
ElementInputHandler::new(bounds, self.editor.clone()),
|
||||
);
|
||||
|
||||
let scrolled = self.scrolled.clone();
|
||||
let font_size = self.style.font_size.to_pixels(px(4.));
|
||||
cx.on_mouse_event(move |scroll: &ScrollWheelEvent, _dispatch, cx| {
|
||||
match scroll.delta {
|
||||
ScrollDelta::Lines(lines) => scrolled.set({
|
||||
let lines_y = lines.y.ceil() as i32;
|
||||
scrolled.get().saturating_add_signed(lines_y as isize)
|
||||
}),
|
||||
ScrollDelta::Pixels(pix) => scrolled.set({
|
||||
let px_y = (pix.y.ceil().0 / font_size.0) as i32;
|
||||
scrolled.get().saturating_add_signed(px_y as isize)
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
cx.with_text_style(
|
||||
Some(TextStyleRefinement {
|
||||
font_size: Some(self.style.font_size),
|
||||
font_family: Some(self.style.font_family),
|
||||
color: self
|
||||
.style
|
||||
.hl_theme
|
||||
.settings
|
||||
.foreground
|
||||
.map(hsla_from_syntect),
|
||||
background_color: self
|
||||
.style
|
||||
.hl_theme
|
||||
.settings
|
||||
.background
|
||||
.map(hsla_from_syntect),
|
||||
..Default::default()
|
||||
}),
|
||||
|cx| {
|
||||
todo!("draw text??")
|
||||
request_layout
|
||||
.styled
|
||||
.iter_mut()
|
||||
.for_each(|(id, styled, bounds)| {
|
||||
styled.paint(None, *bounds, &mut (), &mut (), cx);
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use widestring::Utf16Str;
|
||||
use widestring::{Utf16Str, Utf16String};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
@ -41,6 +41,30 @@ impl ViewInputHandler for Editor {
|
|||
element_bounds: Bounds<Pixels>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<Bounds<Pixels>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn selected_text_range(
|
||||
&mut self,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> Option<std::ops::Range<usize>> {
|
||||
self.buf.read(cx).selected.clone()
|
||||
}
|
||||
|
||||
fn replace_text_in_range(
|
||||
&mut self,
|
||||
range: Option<std::ops::Range<usize>>,
|
||||
text: &str,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let text = Utf16String::from_str(text);
|
||||
self.buf.update(cx, |buf, cx| {
|
||||
if let Some(range) = range {
|
||||
buf.text.replace_range(range, &text)
|
||||
} else {
|
||||
buf.text = text;
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn replace_and_mark_text_in_range(
|
||||
|
@ -50,7 +74,13 @@ impl ViewInputHandler for Editor {
|
|||
new_selected_range: Option<std::ops::Range<usize>>,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let new_text = Utf16String::from_str(new_text);
|
||||
self.buf.update(cx, |buf, cx| {
|
||||
if let Some(range) = range {
|
||||
buf.text.replace_range(range, &new_text)
|
||||
} else {
|
||||
buf.text = new_text;
|
||||
}
|
||||
buf.marked = new_selected_range;
|
||||
})
|
||||
}
|
||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -8,10 +8,16 @@ mod editor;
|
|||
|
||||
struct Nite {
|
||||
editor: View<editor::Editor>,
|
||||
logger: Logger
|
||||
logger: Logger,
|
||||
}
|
||||
|
||||
type Logger = funnylog::Logger<Arc<funnylog::IgnoreError<funnylog::filter::FilterDrain<funnylog::terminal::TerminalDrain<std::io::Stderr>>>>>;
|
||||
type Logger = funnylog::Logger<
|
||||
Arc<
|
||||
funnylog::IgnoreError<
|
||||
funnylog::filter::FilterDrain<funnylog::terminal::TerminalDrain<std::io::Stderr>>,
|
||||
>,
|
||||
>,
|
||||
>;
|
||||
|
||||
impl Render for Nite {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
|
@ -19,8 +25,8 @@ impl Render for Nite {
|
|||
.flex()
|
||||
.size(Length::Definite(DefiniteLength::Fraction(1f32)))
|
||||
.bg(transparent_black())
|
||||
.justify_center()
|
||||
.items_center()
|
||||
.justify_start()
|
||||
.items_start()
|
||||
.text_xl()
|
||||
.text_color(white())
|
||||
.font_family("ComicShannsMono Nerd Font Mono")
|
||||
|
@ -29,8 +35,13 @@ impl Render for Nite {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let drain = Arc::new(funnylog::terminal::TerminalConfig::default().to_stderr().env_filter("RUST_LOG").ignore_error());
|
||||
funnylog::stdlog::setup(drain.clone());
|
||||
let drain = Arc::new(
|
||||
funnylog::terminal::TerminalConfig::default()
|
||||
.to_stderr()
|
||||
.env_filter("RUST_LOG")
|
||||
.ignore_error(),
|
||||
);
|
||||
funnylog::stdlog::setup(drain.clone()).unwrap();
|
||||
let logger = Logger::new(drain);
|
||||
|
||||
App::new().run(|cx| {
|
||||
|
@ -41,9 +52,13 @@ fn main() {
|
|||
|cx| {
|
||||
funnylog::info!(logger, "Hello from nite");
|
||||
|
||||
let settings = cx.new_model(|_cx| editor::EditorSettings::load_defaults());
|
||||
cx.new_view(|cx| Nite {
|
||||
editor: editor::Editor::make(cx),
|
||||
logger
|
||||
editor: editor::Editor::make(
|
||||
cx,
|
||||
settings,
|
||||
),
|
||||
logger,
|
||||
})
|
||||
},
|
||||
);
|
||||
|
|
Loading…
Reference in a new issue