forked from martanne/vis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
editor.h
324 lines (291 loc) · 10.8 KB
/
editor.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
#ifndef EDITOR_H
#define EDITOR_H
#include <signal.h>
#include <stddef.h>
#include <stdbool.h>
#include <setjmp.h>
typedef struct Editor Editor;
typedef struct File File;
typedef struct Win Win;
#include "ui.h"
#include "view.h"
#include "register.h"
#include "macro.h"
#include "syntax.h"
#include "ring-buffer.h"
#include "map.h"
#include "text-regex.h"
typedef union {
bool b;
int i;
const char *s;
void (*w)(View*); /* generic window commands */
void (*f)(Editor*); /* generic editor commands */
} Arg;
#define MAX_KEYS 2
typedef Key KeyCombo[MAX_KEYS];
typedef struct {
KeyCombo key;
void (*func)(const Arg *arg);
const Arg arg;
} KeyBinding;
typedef struct Mode Mode;
struct Mode {
Mode *parent; /* if no match is found in this mode, search will continue there */
KeyBinding *bindings; /* NULL terminated array of keybindings for this mode */
const char *name; /* descriptive, user facing name of the mode */
bool isuser; /* whether this is a user or internal mode */
bool common_prefix; /* whether the first key in this mode is always the same */
void (*enter)(Mode *old); /* called right before the mode becomes active */
void (*leave)(Mode *new); /* called right before the mode becomes inactive */
bool (*unknown)(KeyCombo); /* called whenever a key combination is not found in this mode,
the return value determines whether parent modes will be searched */
void (*input)(const char*, size_t); /* called whenever a key is not found in this mode and all its parent modes */
void (*idle)(void); /* called whenever a certain idle time i.e. without any user input elapsed */
time_t idle_timeout; /* idle time in seconds after which the registered function will be called */
bool visual; /* whether text selection is possible in this mode */
};
typedef struct {
char *name; /* is used to match against argv[0] to enable this config */
Mode *mode; /* default mode in which the editor should start in */
bool (*keypress)(Key*); /* called before any other keybindings are checked,
* return value decides whether key should be ignored */
} Config;
typedef struct {
int count; /* how many times should the command be executed? */
Register *reg; /* always non-NULL, set to a default register */
Filerange range; /* which part of the file should be affected by the operator */
size_t pos; /* at which byte from the start of the file should the operation start? */
bool linewise; /* should the changes always affect whole lines? */
const Arg *arg; /* arbitrary arguments */
} OperatorContext;
typedef struct {
size_t (*func)(OperatorContext*); /* operator logic, returns new cursor position */
} Operator;
typedef struct {
size_t (*cmd)(const Arg*); /* a custom movement based on user input from vis.c */
size_t (*view)(Cursor*); /* a movement based on current window content from view.h */
size_t (*txt)(Text*, size_t pos); /* a movement form text-motions.h */
size_t (*file)(File*, size_t pos);
enum {
LINEWISE = 1 << 0,
CHARWISE = 1 << 1,
INCLUSIVE = 1 << 2,
EXCLUSIVE = 1 << 3,
IDEMPOTENT = 1 << 4,
JUMP = 1 << 5,
} type;
int count;
} Movement;
typedef struct {
Filerange (*range)(Text*, size_t pos); /* a text object from text-objects.h */
enum {
INNER,
OUTER,
} type;
} TextObject;
typedef struct { /** collects all information until an operator is executed */
int count;
int type;
const Operator *op;
const Movement *movement;
const TextObject *textobj;
Register *reg;
int mark;
Arg arg;
} Action;
enum CmdOpt { /* option flags for command definitions */
CMD_OPT_NONE, /* no option (default value) */
CMD_OPT_FORCE, /* whether the command can be forced by appending '!' */
CMD_OPT_ARGS, /* whether the command line should be parsed in to space
* separated arguments to placed into argv, otherwise argv[1]
* will contain the remaining command line unmodified */
};
typedef struct { /* command definitions for the ':'-prompt */
const char *name[3]; /* name and optional alias for the command */
/* command logic called with a NULL terminated array of arguments.
* argv[0] will be the command name */
bool (*cmd)(Filerange*, enum CmdOpt opt, const char *argv[]);
enum CmdOpt opt; /* command option flags */
} Command;
enum Reg {
REG_a,
REG_b,
REG_c,
REG_d,
REG_e,
REG_f,
REG_g,
REG_h,
REG_i,
REG_j,
REG_k,
REG_l,
REG_m,
REG_n,
REG_o,
REG_p,
REG_q,
REG_r,
REG_s,
REG_t,
REG_u,
REG_v,
REG_w,
REG_x,
REG_y,
REG_z,
REG_DEFAULT,
REG_LAST,
};
enum Mark {
MARK_a,
MARK_b,
MARK_c,
MARK_d,
MARK_e,
MARK_f,
MARK_g,
MARK_h,
MARK_i,
MARK_j,
MARK_k,
MARK_l,
MARK_m,
MARK_n,
MARK_o,
MARK_p,
MARK_q,
MARK_r,
MARK_s,
MARK_t,
MARK_u,
MARK_v,
MARK_w,
MARK_x,
MARK_y,
MARK_z,
MARK_SELECTION_START,
MARK_SELECTION_END,
MARK_LAST,
};
struct File {
Text *text;
const char *name;
volatile sig_atomic_t truncated;
bool is_stdin;
struct stat stat;
int refcount;
Mark marks[MARK_LAST];
File *next, *prev;
};
typedef struct {
size_t index; /* #number of changes */
size_t pos; /* where the current change occured */
} ChangeList;
struct Win {
Editor *editor; /* editor instance to which this window belongs */
UiWin *ui;
File *file; /* file being displayed in this window */
View *view; /* currently displayed part of underlying text */
ViewEvent events;
RingBuffer *jumplist; /* LRU jump management */
ChangeList changelist; /* state for iterating through least recently changes */
Win *prev, *next; /* neighbouring windows */
};
#define MACRO_LAST 26
struct Editor {
Ui *ui;
File *files;
Win *windows; /* list of windows */
Win *win; /* currently active window */
Syntax *syntaxes; /* NULL terminated array of syntax definitions */
Register registers[REG_LAST]; /* register used for copy and paste */
Macro macros[MACRO_LAST]; /* recorded macros */
Macro *recording, *last_recording;/* currently and least recently recorded macro */
Win *prompt; /* 1-line height window to get user input */
Win *prompt_window; /* window which was focused before prompt was shown */
char prompt_type; /* command ':' or search '/','?' prompt */
Regex *search_pattern; /* last used search pattern */
char search_char[8]; /* last used character to search for via 'f', 'F', 't', 'T' */
int last_totill; /* last to/till movement used for ';' and ',' */
int tabwidth; /* how many spaces should be used to display a tab */
bool expandtab; /* whether typed tabs should be converted to spaces */
bool autoindent; /* whether indentation should be copied from previous line on newline */
Map *cmds; /* ":"-commands, used for unique prefix queries */
Map *options; /* ":set"-options */
Buffer buffer_repeat; /* holds data to repeat last insertion/replacement */
Action action; /* current action which is in progress */
Action action_prev; /* last operator action used by the repeat '.' key */
Mode *mode; /* currently active mode, used to search for keybindings */
Mode *mode_prev; /* previsouly active user mode */
Mode *mode_before_prompt; /* user mode which was active before entering prompt */
volatile bool running; /* exit main loop once this becomes false */
volatile sig_atomic_t cancel_filter; /* abort external command */
volatile sig_atomic_t sigbus;
sigjmp_buf sigbus_jmpbuf;
};
Editor *editor_new(Ui*);
void editor_free(Editor*);
void editor_resize(Editor*);
void editor_draw(Editor*);
void editor_update(Editor*);
void editor_suspend(Editor*);
/* these function operate on the currently focused window but make sure
* that all windows which show the affected region are redrawn too. */
void editor_insert_key(Editor*, const char *data, size_t len);
void editor_replace_key(Editor*, const char *data, size_t len);
void editor_insert(Editor*, size_t pos, const char *data, size_t len);
void editor_delete(Editor*, size_t pos, size_t len);
void editor_replace(Editor*, size_t pos, const char *data, size_t len);
/* set tabwidth (must be in range [1, 8], affects all windows */
void editor_tabwidth_set(Editor*, int tabwidth);
int editor_tabwidth_get(Editor*);
/* load a set of syntax highlighting definitions which will be associated
* to the underlying window based on the file type loaded.
*
* The parameter `syntaxes' has to point to a NULL terminated array.
*/
bool editor_syntax_load(Editor*, Syntax *syntaxes);
void editor_syntax_unload(Editor*);
/* creates a new window, and loads the given file. if filename is NULL
* an unamed / empty buffer is created. If the given file is already opened
* in another window, share the underlying text that is changes will be
* visible in both windows */
bool editor_window_new(Editor*, const char *filename);
/* reload the file currently displayed in the window from disk */
bool editor_window_reload(Win*);
void editor_window_close(Win*);
/* split the given window. changes to the displayed text will be reflected
* in both windows */
bool editor_window_split(Win*);
/* focus the next / previous window */
void editor_window_next(Editor*);
void editor_window_prev(Editor*);
/* set the filename of the file displayed in this window */
void editor_window_name(Win*, const char *filename);
void editor_window_jumplist_add(Win*, size_t pos);
size_t editor_window_jumplist_prev(Win*);
size_t editor_window_jumplist_next(Win*);
void editor_window_jumplist_invalidate(Win*);
size_t editor_window_changelist_prev(Win*);
size_t editor_window_changelist_next(Win*);
/* rearrange all windows either vertically or horizontally */
void editor_windows_arrange(Editor*, enum UiLayout);
/* display a user prompt with a certain title and default text */
void editor_prompt_show(Editor*, const char *title, const char *text);
/* hide the user prompt if it is currently shown */
void editor_prompt_hide(Editor*);
/* return the content of the command prompt in a malloc(3)-ed string
* which the call site has to free. */
char *editor_prompt_get(Editor*);
/* replace the current command line content with the one given */
void editor_prompt_set(Editor*, const char *line);
/* display a message to the user */
void editor_info_show(Editor*, const char *msg, ...);
void editor_info_hide(Editor*);
void editor_window_options(Win*, enum UiOption options);
/* look up a curses color pair for the given combination of fore and
* background color */
short editor_color_get(short fg, short bg);
#endif