sdl_runtime_compiler git · main
SDL3 game for running and compiling code at runtime
C++ 72.3% C 26.2%git clone https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler.gitwget https://git.christianimmanuel.de/sdl-graphics/sdl_runtime_compiler/archive/sdl_runtime_compiler.tar.gzsrc/text/vim_buffer.hpp raw
#pragma once
#include <algorithm>
#include <cstdint>
#include <string>
#include <vector>
namespace
Nimbin
{
class VimBuffer {
public:
enum class Mode : uint8_t { Normal, Insert, Command };
enum class Signal : uint8_t {
None,
Exit,
Help,
Write,
WriteQuit,
QuitDiscard
};
void key_char (char c);
void key_enter ();
void key_backspace();
void key_escape ();
void key_tab ();
void key_redo (); // ctrl+r
void load (const std::vector<std::string>& src);
Signal take_Signal();
void mark_Saved ();
// Shoot-merge: splice a whole word into line `row` at character `col`,
// adding surrounding spaces so it tokenizes back out as its own token.
// `col` is expected pre-snapped to an inter-token gap by the caller
// (Text::Handler::attach). Clamps row/col, bumps version, marks dirty.
void insert_Word_At(int row, int col, const std::string& word, bool new_line = false);
bool is_Empty() const { return _lines.size() == 1 && _lines[0].empty(); }
const std::vector<std::string>&
get_Lines () const { return _lines; }
int get_Row () const { return _row; }
int get_Col () const { return _col; }
Mode get_Mode () const { return _mode; }
unsigned
get_Version () const { return _version; }
const std::string&
get_Cmdline () const { return _cmd; }
const std::string&
get_Status () const { return _status; }
// Pending operator + count for the bottom-right "showcmd" area, e.g. "d",
// "2d", "c", "g", or a bare count "3". Empties as soon as the command
// completes (both _pending and _count are cleared on dispatch).
std::string get_ShowCmd() const
{
std::string s;
if (_count > 0) s += std::to_string(_count);
s += _pending;
return s;
}
void start_Insert() { _mode = Mode::Insert; _col = 0; touch(); }
void enter_Insert() { _mode = Mode::Insert; clamp_Col(); touch(); } // insert at current cursor
void set_Cursor(int row, int col)
{
if (_lines.empty()) { _row = 0; _col = 0; return; }
_row = (row < 0) ? 0
: (row >= (int)_lines.size() ? (int)_lines.size() - 1 : row);
_col = (col < 0) ? 0 : col;
clamp_Col();
touch();
}
private:
struct Snapshot { std::vector<std::string> lines; int row; int col; };
std::vector<Snapshot> _undo;
std::vector<Snapshot> _redo;
std::vector<std::string> _saved;
std::vector<std::string> _lines{ "" };
Mode _mode = Mode::Normal;
Signal _sig = Signal::None;
std::string _pending;
std::string _cmd;
std::string _status;
std::string _register;
unsigned _version = 0;
int _row = 0, _col = 0;
int _count = 0;
bool _dirty = false;
bool _reg_linewise = false;
void touch ();
void clamp_Col ();
void normal_Key (char c);
void insert_Char (char c);
void split_Line ();
void backspace_Insert();
void delete_Chars (int n);
void delete_Lines (int n);
void open_Below ();
void open_Above ();
void run_Command ();
void cancel_Command ();
// word motion (whitespace-delimited, matching the tokenizer)
int word_EndCol (int times) const; // exclusive end of word(s) from _col (for cw)
int next_WordCol (int times) const; // start of the n-th next word (for dw/yw/w)
int end_WordCol (int times) const; // last char of the n-th word fwd (for e)
int prev_WordCol (int times) const; // start of the n-th word back (for b)
// undo/redo
void push_Undo (); // snapshot current state, clear redo
void undo ();
void redo ();
// yank / paste / change
void yank_Lines (int n); // linewise yank n lines from _row
void op_ToNextWord (int times, bool del, bool yank); // dw / yw
void op_ChangeWord (int times); // cw
void change_Line (); // cc (register filled by caller)
void paste_After ();
void paste_Before ();
// indentation
void indent_Lines (int n, int dir); // dir +1 = indent, -1 = dedent
bool is_Dirty () const;
int get_LineLen () const;
int get_Eff () const;
int get_ClampRow (int r) const;
};
} // namespace Nimbin