hjkl_engine/lib.rs
1//! Vim-mode editor engine built on top of [`hjkl_buffer`].
2//!
3//! Exposes an [`Editor`] that is fully toolkit-agnostic. Covers the bulk
4//! of vim's normal / insert / visual / visual-line / visual-block modes,
5//! text-object operators, dot-repeat, and ex-command handling
6//! (`:s/foo/bar/g`, `:w`, `:q`, `:noh`, ...). Rendering goes through
7//! `hjkl_buffer::BufferView`; selection / gutter highlights are painted in
8//! the same single-pass as text. TUI/crossterm adapters live in the
9//! `hjkl-engine-tui` companion crate.
10//!
11//! Imported wholesale from sqeel-vim with full git history. The trait
12//! extraction (Selection / SelectionSet / Buffer + Host sub-traits) lands
13//! progressively under [`crate::types`]. Pre-1.0 churn — the public surface
14//! may change in patch bumps. See [docs.rs](https://docs.rs/hjkl-engine) for
15//! the canonical API reference.
16//!
17//! The legacy public surface is intentionally narrow:
18//!
19//! - [`Editor`] — the editor widget.
20//! - [`KeybindingMode`] / [`VimMode`] — mode enums used by host apps.
21//! - [`ex::run`] / [`ex::ExEffect`] — drive ex-mode commands.
22
23mod buf_helpers;
24mod buffer_impl;
25mod editor;
26mod input;
27pub mod keymap_motion;
28pub mod motions;
29mod registers;
30pub mod search;
31pub mod substitute;
32pub mod types;
33mod viewport_math;
34mod vim;
35
36pub use editor::{Editor, LspIntent, MarkJump, StepBookkeeping};
37pub use input::{Input, Key, decode_macro, from_planned as decode_planned_input};
38pub use registers::{Registers, Slot};
39
40pub use buffer_impl::{BufferFoldProvider, BufferFoldProviderMut};
41pub use keymap_motion::MotionKind;
42pub use substitute::{
43 SubstError, SubstFlags, SubstituteCmd, SubstituteOutcome, apply_substitute, parse_substitute,
44};
45pub use types::{
46 Attrs, Buffer, BufferEdit, BufferId, Color, ContentEdit, Cursor, CursorShape, DefaultHost,
47 Edit, EditorSnapshot, EngineError, FoldOp, FoldProvider, Highlight, HighlightKind, Host,
48 Input as PlannedInput, Mode, Modifiers, MouseEvent, MouseKind, NoopFoldProvider, OptionValue,
49 Options, Pos, Query, RenderFrame, Search, Selection, SelectionKind, SelectionSet, SnapshotMode,
50 SpecialKey, Style, Viewport, WrapMode,
51};
52pub use vim::{
53 InsertDir, InsertEntry, InsertReason, InsertSession, LastChange, LastVisual, Motion, Operator,
54 Pending, RangeKind, ScrollDir, SearchPrompt, op_is_change, parse_motion,
55};
56
57/// The FSM-internal mode discriminator used by `Editor::fsm_mode()` and
58/// `Editor::set_fsm_mode()`. Re-exported as `FsmMode` to avoid clashing with
59/// the `types::Mode` buffer-side enum that is already exported as `Mode`.
60///
61/// Used by `hjkl-vim::normal` and `hjkl-vim::dispatch_input` for mode
62/// comparisons.
63pub use vim::Mode as FsmMode;
64
65// 0.0.32 dropped the `#[deprecated]` re-export aliases introduced at
66// 0.0.31 (`SpecBuffer`, `SpecBufferEdit`, `EditOp`, `PlannedViewport`).
67// Consumers must use the canonical names: `Buffer`, `BufferEdit`,
68// `Edit`, `Viewport`.
69
70/// Which keyboard discipline the editor uses. Currently vim-only, but
71/// kept as an enum so future emacs / plain bindings can slot in without
72/// touching the public signature.
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
74pub enum KeybindingMode {
75 #[default]
76 Vim,
77}
78
79#[cfg(feature = "serde")]
80impl serde::Serialize for KeybindingMode {
81 fn serialize<S: serde::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
82 s.serialize_str("vim")
83 }
84}
85
86#[cfg(feature = "serde")]
87impl<'de> serde::Deserialize<'de> for KeybindingMode {
88 fn deserialize<D: serde::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
89 let _ = String::deserialize(d)?;
90 Ok(KeybindingMode::Vim)
91 }
92}
93
94/// Coarse vim-mode a host app can display in its status line.
95#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
96pub enum VimMode {
97 #[default]
98 Normal,
99 Insert,
100 Visual,
101 VisualLine,
102 VisualBlock,
103}