hjkl_editor/lib.rs
1//! # hjkl-editor
2//!
3//! Front door for the hjkl modal editor stack. Re-exports the working
4//! parts of [`hjkl_engine`] and [`hjkl_buffer`] under a curated
5//! namespace so downstream consumers (sqeel, buffr, hjkl binary) add
6//! one dependency instead of three and don't need to know the
7//! crate-split.
8//!
9//! Two layers ride alongside each other during the 0.0.x churn:
10//!
11//! - **Legacy surface** (today's runtime): the [`runtime`] module
12//! re-exports the existing [`Editor`], [`KeybindingMode`], [`VimMode`],
13//! [`Input`], [`Key`], [`SearchPrompt`], [`Registers`], [`Slot`], and
14//! [`LspIntent`]. This is what sqeel-tui consumes today.
15//! - **Planned surface** (0.1.0 SPEC): the [`spec`] module re-exports
16//! the additive types from [`hjkl_engine::types`] —
17//! [`spec::Pos`], [`spec::Selection`], [`spec::SelectionSet`],
18//! [`spec::Edit`], [`spec::Mode`], [`spec::Style`], [`spec::Highlight`],
19//! [`spec::Options`], [`spec::Input`], [`spec::Host`], [`spec::EngineError`].
20//! Trait extraction will rewire the runtime onto these — once it
21//! ships, [`runtime`] becomes a thin compat layer.
22//!
23//! ## Usage
24//!
25//! ```no_run
26//! use hjkl_editor::buffer;
27//! use hjkl_editor::runtime::{DefaultHost, Editor, Options};
28//!
29//! let mut editor = Editor::new(buffer::Buffer::new(), DefaultHost::new(), Options::default());
30//! editor.set_content("hello world");
31//! ```
32//!
33//! Buffer and rope helpers are re-exported at the [`buffer`] module,
34//! mirroring the [`hjkl_buffer`] surface.
35//!
36//! [`Editor`]: hjkl_engine::Editor
37//! [`KeybindingMode`]: hjkl_engine::KeybindingMode
38//! [`VimMode`]: hjkl_engine::VimMode
39//! [`Input`]: hjkl_engine::Input
40//! [`Key`]: hjkl_engine::Key
41//! [`SearchPrompt`]: hjkl_engine::SearchPrompt
42//! [`Registers`]: hjkl_engine::Registers
43//! [`Slot`]: hjkl_engine::Slot
44//! [`LspIntent`]: hjkl_engine::LspIntent
45#![forbid(unsafe_code)]
46
47// Ex command driver — relocated from hjkl-engine in 0.0.5. Lives here
48// because ex commands operate over the public Editor surface; engine
49// stays focused on the FSM core.
50mod ex;
51
52pub mod buffer {
53 //! Re-export of [`hjkl_buffer`]'s public surface.
54
55 pub use hjkl_buffer::{
56 Buffer, BufferView, Edit, Fold, Gutter, MotionKind, Position, RowSpan, Selection, Sign,
57 Span, StyleResolver, Viewport, Wrap,
58 };
59}
60
61pub mod runtime {
62 //! Legacy runtime surface — the working sqeel-vim port.
63 //!
64 //! These types drive editing today. The trait extraction lands a
65 //! generic `Editor<B: Buffer, H: Host>` into [`crate::spec`] that
66 //! eventually replaces this surface; pre-1.0 churn means the swap
67 //! can land on a patch bump.
68
69 pub use hjkl_engine::types::{DefaultHost, Options};
70 pub use hjkl_engine::{
71 Editor, Input, Key, KeybindingMode, LspIntent, Registers, SearchPrompt, Slot, VimMode,
72 };
73 pub mod ex {
74 //! Ex command driver — `:s/pat/.../`, `:w`, `:q`, etc.
75 //!
76 //! Lives in this crate (relocated from hjkl-engine in 0.0.5).
77 pub use crate::ex::*;
78 }
79}
80
81pub mod spec {
82 //! Engine trait surface re-exported for consumers.
83 //!
84 //! All types are additive — they coexist with [`crate::runtime`]
85 //! during the churn phase. Trait impls are forthcoming; today the
86 //! types support host-side prep (e.g., buffr-modal's `BuffrHost`).
87
88 pub use hjkl_engine::types::{
89 Attrs, Buffer, BufferEdit, BufferId, Color, Cursor, CursorShape, Edit, EngineError, FoldOp,
90 FoldProvider, Highlight, HighlightKind, Host, Input, Mode, Modifiers, MouseEvent,
91 MouseKind, NoopFoldProvider, Options, Pos, Query, Search, Selection, SelectionKind,
92 SelectionSet, SpecialKey, Style, Viewport,
93 };
94 pub use hjkl_engine::{BufferFoldProvider, BufferFoldProviderMut};
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn editor_constructs() {
103 let _ = runtime::Editor::new(
104 buffer::Buffer::new(),
105 runtime::DefaultHost::new(),
106 runtime::Options::default(),
107 );
108 }
109
110 #[test]
111 fn buffer_constructs() {
112 let _ = buffer::Buffer::from_str("hello\nworld");
113 }
114
115 #[test]
116 fn spec_options_default() {
117 let opts = spec::Options::default();
118 assert_eq!(opts.tabstop, 4);
119 }
120
121 #[test]
122 fn spec_selection_set_default() {
123 let set = spec::SelectionSet::default();
124 assert_eq!(set.items.len(), 1);
125 }
126}