11 #include "ring-buffer.h"
16 /* a mode contains a set of key bindings which are currently valid.
18 * each mode can specify one parent mode which is consultated if a given key
19 * is not found in the current mode. hence the modes form a tree which is
20 * searched from the current mode up towards the root mode until a valid binding
23 * if no binding is found, mode->input(...) is called and the user entered
24 * keys are passed as argument. this is used to change the document content.
26 typedef struct Mode Mode
;
29 Mode
*parent
; /* if no match is found in this mode, search will continue there */
31 const char *name
; /* descriptive, user facing name of the mode */
32 const char *status
; /* name displayed in the window status bar */
33 const char *help
; /* short description used by :help */
34 void (*enter
)(Vis
*, Mode
*old
); /* called right before the mode becomes active */
35 void (*leave
)(Vis
*, Mode
*new); /* called right before the mode becomes inactive */
36 void (*input
)(Vis
*, const char*, size_t); /* called whenever a key is not found in this mode and all its parent modes */
37 void (*idle
)(Vis
*); /* called whenever a certain idle time i.e. without any user input elapsed */
38 time_t idle_timeout
; /* idle time in seconds after which the registered function will be called */
39 bool visual
; /* whether text selection is possible in this mode */
44 bool linewise
; /* place register content on a new line when inserting? */
54 struct OperatorContext
{
55 int count
; /* how many times should the command be executed? */
56 Register
*reg
; /* always non-NULL, set to a default register */
57 size_t reg_slot
; /* register slot to use */
58 Filerange range
; /* which part of the file should be affected by the operator */
59 size_t pos
; /* at which byte from the start of the file should the operation start? */
60 size_t newpos
; /* new position after motion or EPOS if none given */
61 bool linewise
; /* should the changes always affect whole lines? */
62 const Arg
*arg
; /* arbitrary arguments */
63 void *context
; /* used by user-registered operators */
67 /* operator logic, returns new cursor position, if EPOS is
68 * the cursor is disposed (except if it is the primary one) */
69 VisOperatorFunction
*func
;
73 typedef struct { /* Motion implementation, takes a cursor postion and returns a new one */
74 /* TODO: merge types / use union to save space */
75 size_t (*cur
)(Cursor
*);
76 size_t (*txt
)(Text
*, size_t pos
);
77 size_t (*file
)(Vis
*, File
*, size_t pos
);
78 size_t (*vis
)(Vis
*, Text
*, size_t pos
);
79 size_t (*view
)(Vis
*, View
*);
80 size_t (*win
)(Vis
*, Win
*, size_t pos
);
81 size_t (*user
)(Vis
*, Win
*, void*, size_t pos
);
83 LINEWISE
= VIS_MOTIONTYPE_LINEWISE
, /* should the covered range be extended to whole lines? */
84 CHARWISE
= VIS_MOTIONTYPE_CHARWISE
, /* scrolls window content until position is visible */
85 INCLUSIVE
= 1 << 2, /* should new position be included in operator range? */
86 LINEWISE_INCLUSIVE
= 1 << 3, /* inclusive, but only if motion is linewise? */
87 IDEMPOTENT
= 1 << 4, /* does the returned postion remain the same if called multiple times? */
88 JUMP
= 1 << 5, /* should the resulting position of the motion be recorded in the jump list? */
89 COUNT_EXACT
= 1 << 6, /* fail (keep initial position) if count can not be satisfied exactly */
95 /* gets a cursor position and returns a file range (or text_range_empty())
96 * representing the text object containing the position. */
97 Filerange (*txt
)(Text
*, size_t pos
);
98 Filerange (*vis
)(Vis
*, Text
*, size_t pos
);
99 Filerange (*user
)(Vis
*, Win
*, void *data
, size_t pos
);
101 TEXTOBJECT_DELIMITED_INNER
= 1 << 0, /* single byte delimited, inner variant */
102 TEXTOBJECT_DELIMITED_OUTER
= 1 << 1, /* single byte delimited, outer variant */
103 TEXTOBJECT_NON_CONTIGUOUS
= 1 << 2, /* multiple applications yield a split range */
104 TEXTOBJECT_EXTEND_FORWARD
= 1 << 3, /* multiple applications extend towards the end of file (default) */
105 TEXTOBJECT_EXTEND_BACKWARD
= 1 << 4, /* multiple applications extend towards the begin of file */
110 /* a macro is just a sequence of symbolic keys as received from ui->getkey */
111 typedef Buffer Macro
;
112 #define macro_init buffer_init
113 #define macro_release buffer_release
114 #define macro_reset buffer_clear
115 #define macro_append buffer_append0
117 typedef struct { /** collects all information until an operator is executed */
120 enum VisMotionType type
;
122 const Movement
*movement
;
123 const TextObject
*textobj
;
130 typedef struct Change Change
;
132 Change
*changes
; /* all changes in monotonically increasing file position */
133 Change
*latest
; /* most recent change */
134 enum SamError error
; /* non-zero in case something went wrong */
137 struct File
{ /* shared state among windows displaying the same file */
138 Text
*text
; /* data structure holding the file content */
139 const char *name
; /* file name used when loading/saving */
140 volatile sig_atomic_t truncated
; /* whether the underlying memory mapped region became invalid (SIGBUS) */
141 int fd
; /* output file descriptor associated with this file or -1 if loaded by file name */
142 bool internal
; /* whether it is an internal file (e.g. used for the prompt) */
143 struct stat stat
; /* filesystem information when loaded/saved, used to detect changes outside the editor */
144 int refcount
; /* how many windows are displaying this file? (always >= 1) */
145 Mark marks
[VIS_MARK_INVALID
]; /* marks which are shared across windows */
146 enum TextSaveMethod save_method
; /* whether the file is saved using rename(2) or overwritten */
147 Transcript transcript
; /* keeps track of changes performed by sam commands */
152 time_t state
; /* state of the text, used to invalidate change list */
153 size_t index
; /* #number of changes */
154 size_t pos
; /* where the current change occured */
158 Vis
*vis
; /* editor instance to which this window belongs to */
159 UiWin
*ui
; /* ui object handling visual appearance of this window */
160 File
*file
; /* file being displayed in this window */
161 View
*view
; /* currently displayed part of underlying text */
162 RingBuffer
*jumplist
; /* LRU jump management */
163 ChangeList changelist
; /* state for iterating through least recently changes */
164 Mode modes
[VIS_MODE_INVALID
]; /* overlay mods used for per window key bindings */
165 Win
*parent
; /* window which was active when showing the command prompt */
166 Mode
*parent_mode
; /* mode which was active when showing the command prompt */
167 Win
*prev
, *next
; /* neighbouring windows */
171 Ui
*ui
; /* user interface repsonsible for visual appearance */
172 File
*files
; /* all files currently managed by this editor instance */
173 File
*command_file
; /* special internal file used to store :-command prompt */
174 File
*search_file
; /* special internal file used to store /,? search prompt */
175 File
*error_file
; /* special internal file used to store lua error messages */
176 Win
*windows
; /* all windows currently managed by this editor instance */
177 Win
*win
; /* currently active/focused window */
178 Win
*message_window
; /* special window to display multi line messages */
179 Register registers
[VIS_REG_INVALID
]; /* registers used for text manipulations yank/put etc. and macros */
180 Macro
*recording
, *last_recording
; /* currently (if non NULL) and least recently recorded macro */
181 const Macro
*replaying
; /* macro currently being replayed */
182 Macro
*macro_operator
; /* special macro used to repeat certain operators */
183 Mode
*mode_before_prompt
; /* user mode which was active before entering prompt */
184 char search_char
[8]; /* last used character to search for via 'f', 'F', 't', 'T' */
185 int last_totill
; /* last to/till movement used for ';' and ',' */
186 int search_direction
; /* used for `n` and `N` */
187 int tabwidth
; /* how many spaces should be used to display a tab */
188 bool expandtab
; /* whether typed tabs should be converted to spaces */
189 bool autoindent
; /* whether indentation should be copied from previous line on newline */
190 bool change_colors
; /* whether to adjust 256 color palette for true colors */
191 char *shell
; /* shell used to launch external commands */
192 Map
*cmds
; /* ":"-commands, used for unique prefix queries */
193 Map
*usercmds
; /* user registered ":"-commands */
194 Map
*options
; /* ":set"-options */
195 Map
*keymap
; /* key translation before any bindings are matched */
196 bool keymap_disabled
; /* ignore key map for next key press, gets automatically re-enabled */
197 char key
[VIS_KEY_LENGTH_MAX
]; /* last pressed key as reported from the UI */
198 char key_current
[VIS_KEY_LENGTH_MAX
];/* current key being processed by the input queue */
199 char key_prev
[VIS_KEY_LENGTH_MAX
]; /* previous key which was processed by the input queue */
200 Buffer input_queue
; /* holds pending input keys */
201 bool errorhandler
; /* whether we are currently in an error handler, used to avoid recursion */
202 Action action
; /* current action which is in progress */
203 Action action_prev
; /* last operator action used by the repeat (dot) command */
204 Mode
*mode
; /* currently active mode, used to search for keybindings */
205 Mode
*mode_prev
; /* previsouly active user mode */
206 bool initialized
; /* whether UI and Lua integration has been initialized */
207 int nesting_level
; /* parsing state to hold keep track of { } nesting level */
208 volatile bool running
; /* exit main loop once this becomes false */
209 int exit_status
; /* exit status when terminating main loop */
210 volatile sig_atomic_t interrupted
; /* abort command (SIGINT occured) */
211 volatile sig_atomic_t sigbus
; /* one of the memory mapped region became unavailable (SIGBUS) */
212 volatile sig_atomic_t need_resize
; /* need to resize UI (SIGWINCH occured) */
213 volatile sig_atomic_t resume
; /* need to resume UI (SIGCONT occured) */
214 volatile sig_atomic_t terminate
; /* need to terminate we were being killed by SIGTERM */
215 sigjmp_buf sigbus_jmpbuf
; /* used to jump back to a known good state in the mainloop after (SIGBUS) */
216 Map
*actions
; /* registered editor actions / special keys commands */
217 Array actions_user
; /* dynamically allocated editor actions */
218 lua_State
*lua
; /* lua context used for syntax highligthing */
231 VIS_EVENT_FILE_SAVE_PRE
,
232 VIS_EVENT_FILE_SAVE_POST
,
233 VIS_EVENT_FILE_CLOSE
,
236 VIS_EVENT_WIN_HIGHLIGHT
,
237 VIS_EVENT_WIN_STATUS
,
240 bool vis_event_emit(Vis
*, enum VisEvents
, ...);
244 VIS_HELP_DECL(const char *help
;)
247 typedef MarkDef RegisterDef
;
249 /** stuff used by multiple of the vis-* files */
251 extern Mode vis_modes
[VIS_MODE_INVALID
];
252 extern const Movement vis_motions
[VIS_MOVE_INVALID
];
253 extern const Operator vis_operators
[VIS_OP_INVALID
];
254 extern const TextObject vis_textobjects
[VIS_TEXTOBJECT_INVALID
];
255 extern const MarkDef vis_marks
[VIS_MARK_a
];
256 extern const RegisterDef vis_registers
[VIS_REG_a
];
258 void macro_operator_stop(Vis
*vis
);
259 void macro_operator_record(Vis
*vis
);
261 void vis_do(Vis
*vis
);
262 void action_reset(Action
*);
263 size_t vis_text_insert_nl(Vis
*, Text
*, size_t pos
);
265 void mode_set(Vis
*vis
, Mode
*new_mode
);
266 Macro
*macro_get(Vis
*vis
, enum VisRegister
);
268 void window_selection_save(Win
*win
);
269 Win
*window_new_file(Vis
*, File
*, enum UiOption
);
271 const char *file_name_get(File
*);
272 void file_name_set(File
*, const char *name
);
274 bool register_init(Register
*);
275 void register_release(Register
*);
277 const char *register_get(Vis
*, Register
*, size_t *len
);
278 const char *register_slot_get(Vis
*, Register
*, size_t slot
, size_t *len
);
280 bool register_put0(Vis
*, Register
*, const char *data
);
281 bool register_put(Vis
*, Register
*, const char *data
, size_t len
);
282 bool register_slot_put(Vis
*, Register
*, size_t slot
, const char *data
, size_t len
);
284 bool register_put_range(Vis
*, Register
*, Text
*, Filerange
*);
285 bool register_slot_put_range(Vis
*, Register
*, size_t slot
, Text
*, Filerange
*);
287 size_t vis_register_count(Vis
*, Register
*);
288 bool register_resize(Register
*, size_t count
);