Skip to main content

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 / View + 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//! - [`VimMode`] — mode enum used by host apps.
21//! - [`ex::run`] / [`ex::ExEffect`] — drive ex-mode commands.
22
23pub mod abbrev;
24pub mod buf_helpers;
25mod buffer_impl;
26mod cursor_move;
27mod discipline;
28mod editor;
29pub mod input;
30pub mod keymap_motion;
31pub mod motions;
32pub mod options_registry;
33pub mod policy;
34mod registers;
35pub mod rope_util;
36pub mod search;
37pub mod selection_shift;
38pub mod substitute;
39pub mod tag;
40pub mod types;
41mod viewport_math;
42
43pub use cursor_move::Move;
44pub use discipline::{DisciplineState, NoDiscipline};
45pub use editor::{
46    ChangeBank, CursorScrollTarget, Editor, GlobalMarks, LspIntent, MarkJump, SearchBank, Settings,
47    UndoGranularity,
48};
49pub use input::{Input, Key, decode_macro, from_planned as decode_planned_input};
50pub use registers::{Registers, Slot};
51pub use selection_shift::{Sel, shift_position, shift_sel};
52pub use viewport_math::rope_line_slice;
53
54pub use buffer_impl::{BufferFoldProvider, BufferFoldProviderMut, SnapshotFoldProvider};
55pub use keymap_motion::MotionKind;
56pub use substitute::{
57    SubstError, SubstFlags, SubstituteCmd, SubstituteMatch, SubstituteOutcome,
58    apply_collected_matches, apply_substitute, collect_substitute_matches, parse_substitute,
59};
60pub use types::{
61    Attrs, BufferEdit, BufferId, Color, ContentEdit, Cursor, CursorShape, DefaultHost, Edit,
62    EditorSnapshot, EngineError, FoldOp, FoldProvider, Highlight, HighlightKind, Host,
63    Input as PlannedInput, Mode, Modifiers, MouseEvent, MouseKind, NoopFoldProvider, OptionValue,
64    Options, Pos, Query, RenderFrame, Search, Selection, SelectionKind, SelectionSet, SnapshotMode,
65    SpecialKey, Style, View, Viewport, WrapMode,
66};
67// The vim FSM itself now lives in `hjkl-vim` (#267). What stays here is the
68// engine-owned substrate it happens to use — abbreviations, the search prompt,
69// scroll/insert directions — plus the shared vocabulary types from
70// `hjkl-vim-types`, which both crates name and neither owns.
71pub use abbrev::{Abbrev, AbbrevTrigger};
72pub use search::SearchPrompt;
73pub use tag::matching_tag_pair;
74pub use types::{InsertDir, ScrollDir};
75
76pub use hjkl_vim_types::{
77    InsertEntry, InsertReason, InsertSession, LastChange, LastVisual, Motion, Operator, Pending,
78    RangeKind,
79};
80
81/// The FSM-internal mode discriminator used by `Editor::fsm_mode()` and
82/// `Editor::set_fsm_mode()`. Re-exported as `FsmMode` to avoid clashing with
83/// the `types::Mode` buffer-side enum that is already exported as `Mode`.
84///
85/// Used by `hjkl-vim::normal` and `hjkl-vim::dispatch_input` for mode
86/// comparisons.
87pub use hjkl_vim_types::Mode as FsmMode;
88
89// 0.0.32 dropped the `#[deprecated]` re-export aliases introduced at
90// 0.0.31 (`SpecBuffer`, `SpecBufferEdit`, `EditOp`, `PlannedViewport`).
91// Consumers must use the canonical names: `View`, `BufferEdit`,
92// `Edit`, `Viewport`.
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}
104
105/// Discipline-agnostic coarse mode for app chrome (status badge, cursor
106/// shape). Unlike [`VimMode`] — which names vim-specific states — `CoarseMode`
107/// is a minimal projection: "are we inserting text, selecting, or idle?"
108///
109/// App chrome reads this instead of `VimMode` so it stays behind the engine's
110/// discipline seam ([`DisciplineState`]): the installed discipline (vim today)
111/// maps its own modes onto these variants via `DisciplineState::coarse_mode`.
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
113pub enum CoarseMode {
114    /// Idle / command-ready (vim Normal).
115    #[default]
116    Normal,
117    /// Text is being inserted at the caret (vim Insert).
118    Insert,
119    /// A character-wise selection is active (vim Visual).
120    Select,
121    /// A line-wise selection is active (vim VisualLine).
122    SelectLine,
123    /// A block / column selection is active (vim VisualBlock).
124    SelectBlock,
125}
126
127/// A read-only *view* layered over the real input [`VimMode`]. Unlike a vim
128/// mode (which decides how keystrokes are interpreted), a `ViewMode` only
129/// changes what the buffer presents — input is still interpreted as Normal.
130///
131/// `Blame` is the git-blame overlay: the editor is read-only and the host
132/// renders per-commit framing. It is only meaningful while the input mode is
133/// `Normal`; any transition to Insert/Visual/etc. drops it back to `Normal`
134/// (see [`Editor::is_blame`]). New read-only overlays (diff, conflict, …)
135/// become additional variants here without touching `VimMode`.
136#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
137pub enum ViewMode {
138    #[default]
139    Normal,
140    Blame,
141}