Skip to main content

cell_sheet_core/help/
entries.rs

1use super::{HelpCategory, HelpEntry};
2
3pub static NORMAL_ENTRIES: &[HelpEntry] = &[
4    HelpEntry {
5        tags: &["count", "[count]", "N"],
6        category: HelpCategory::Normal,
7        summary: "Numeric count prefix",
8        detail: "Type digits before a motion or operator to repeat or scale it,\n\
9                 vim-style. Examples: 5j moves 5 rows down, 10G jumps to row 10,\n\
10                 3dd deletes 3 rows, 4yy yanks 4 rows, 2w hops 2 non-empty cells.\n\
11                 The count is shown in the status line as you type.\n\n\
12                 0 alone goes to the first column; only after a non-zero digit\n\
13                 does 0 extend the count (so 10j really moves 10 rows).\n\n\
14                 Esc cancels a partially-typed count. Counts apply to:\n\
15                 h j k l, Up/Down/Left/Right, w b, gg G, dd yy.\n\n\
16                 Operator-pending counts: you can also place a count between the\n\
17                 operator and the motion (e.g. d3j, y2k). If both an outer count\n\
18                 and an inner motion count are given they multiply: 5d2j clears\n\
19                 10 rows downward from the cursor.",
20    },
21    HelpEntry {
22        tags: &["h"],
23        category: HelpCategory::Normal,
24        summary: "Move cursor left ([count]h)",
25        detail: "Move the cursor one column to the left. Stops at column A.\n\
26                 With a count prefix, moves [count] columns.\n\
27                 Alias: Left arrow",
28    },
29    HelpEntry {
30        tags: &["j"],
31        category: HelpCategory::Normal,
32        summary: "Move cursor down ([count]j)",
33        detail: "Move the cursor one row down. With a count prefix, moves\n\
34                 [count] rows.\nAlias: Down arrow",
35    },
36    HelpEntry {
37        tags: &["k"],
38        category: HelpCategory::Normal,
39        summary: "Move cursor up ([count]k)",
40        detail: "Move the cursor one row up. Stops at row 1. With a count\n\
41                 prefix, moves [count] rows.\nAlias: Up arrow",
42    },
43    HelpEntry {
44        tags: &["l"],
45        category: HelpCategory::Normal,
46        summary: "Move cursor right ([count]l)",
47        detail: "Move the cursor one column to the right. With a count prefix,\n\
48                 moves [count] columns.\nAlias: Right arrow",
49    },
50    HelpEntry {
51        tags: &["gg"],
52        category: HelpCategory::Normal,
53        summary: "Go to first row / row N ([count]gg)",
54        detail: "Move the cursor to row 1, keeping the current column.\n\
55                 With a count prefix, jumps to row [count] (1-indexed).",
56    },
57    HelpEntry {
58        tags: &["G"],
59        category: HelpCategory::Normal,
60        summary: "Go to last row / row N ([count]G)",
61        detail: "Move the cursor to the last row with data, keeping the\n\
62                 current column. With a count prefix, jumps to row [count]\n\
63                 (1-indexed) instead.",
64    },
65    HelpEntry {
66        tags: &["0"],
67        category: HelpCategory::Normal,
68        summary: "Go to first column",
69        detail: "Move the cursor to column A, keeping the current row.",
70    },
71    HelpEntry {
72        tags: &["$"],
73        category: HelpCategory::Normal,
74        summary: "Go to last column",
75        detail: "Move the cursor to the last column with data, keeping the current row.",
76    },
77    HelpEntry {
78        tags: &["w"],
79        category: HelpCategory::Normal,
80        summary: "Next non-empty cell ([count]w)",
81        detail: "Jump to the next non-empty cell to the right in the current\n\
82                 row. With a count prefix, hops [count] non-empty cells.",
83    },
84    HelpEntry {
85        tags: &["b"],
86        category: HelpCategory::Normal,
87        summary: "Previous non-empty cell ([count]b)",
88        detail: "Jump to the previous non-empty cell to the left in the\n\
89                 current row. With a count prefix, hops [count] non-empty\n\
90                 cells back.",
91    },
92    HelpEntry {
93        tags: &["dd"],
94        category: HelpCategory::Normal,
95        summary: "Delete current row ([count]dd)",
96        detail: "Deletes all cells in the current row. With a count prefix,\n\
97                 deletes [count] rows starting at the cursor; the deleted\n\
98                 rows are stored line-wise in the register and can be\n\
99                 pasted as a block with p (below) or P (above). Undoable\n\
100                 with u.\n\n\
101                 To clear a range using a motion instead of repeating the\n\
102                 operator, use d{motion}: see dj, dk, dl, dh.",
103    },
104    HelpEntry {
105        tags: &["dj", "d3j"],
106        category: HelpCategory::Normal,
107        summary: "Clear rows downward (d[count]j)",
108        detail: "Clear the current row and [count] rows below it (content only;\n\
109                 rows are not removed). Without a count, clears the current row\n\
110                 and the one below. An outer count before d multiplies the motion\n\
111                 count: 5d2j clears 10 rows. Undoable with u.",
112    },
113    HelpEntry {
114        tags: &["dk", "d2k"],
115        category: HelpCategory::Normal,
116        summary: "Clear rows upward (d[count]k)",
117        detail: "Clear [count] rows above the cursor and the current row\n\
118                 (content only; rows are not removed). Without a count, clears\n\
119                 the current row and the one above. Undoable with u.",
120    },
121    HelpEntry {
122        tags: &["dl"],
123        category: HelpCategory::Normal,
124        summary: "Clear cells rightward (d[count]l)",
125        detail: "Clear the current cell and [count] cells to the right.\n\
126                 Without a count, clears the current cell and the one to its\n\
127                 right. Undoable with u.",
128    },
129    HelpEntry {
130        tags: &["dh"],
131        category: HelpCategory::Normal,
132        summary: "Clear cells leftward (d[count]h)",
133        detail: "Clear [count] cells to the left and the current cell.\n\
134                 Without a count, clears the cell to the left and the current\n\
135                 cell. Undoable with u.",
136    },
137    HelpEntry {
138        tags: &["yy"],
139        category: HelpCategory::Normal,
140        summary: "Yank current row ([count]yy)",
141        detail: "Copies all cells in the current row to the register. With a\n\
142                 count prefix, yanks [count] rows starting at the cursor.\n\
143                 Paste with p (below) or P (above).\n\n\
144                 To yank a range using a motion, use y{motion}: see yj, yk,\n\
145                 yl, yh.",
146    },
147    HelpEntry {
148        tags: &["yj"],
149        category: HelpCategory::Normal,
150        summary: "Yank rows downward (y[count]j)",
151        detail: "Yank the current row and [count] rows below it into the register.\n\
152                 Paste with p (below) or P (above). An outer count multiplies\n\
153                 the motion count: 5y2j yanks 10 rows.",
154    },
155    HelpEntry {
156        tags: &["yk"],
157        category: HelpCategory::Normal,
158        summary: "Yank rows upward (y[count]k)",
159        detail: "Yank [count] rows above the cursor and the current row into the\n\
160                 register. Paste with p (below) or P (above).",
161    },
162    HelpEntry {
163        tags: &["yl", "y3l", "y4l"],
164        category: HelpCategory::Normal,
165        summary: "Yank cells rightward (y[count]l)",
166        detail: "Yank the current cell and [count] cells to the right into the\n\
167                 register. Without a count, yanks the current cell and the one\n\
168                 to its right. Paste with p.",
169    },
170    HelpEntry {
171        tags: &["yh"],
172        category: HelpCategory::Normal,
173        summary: "Yank cells leftward (y[count]h)",
174        detail: "Yank [count] cells to the left and the current cell into the\n\
175                 register. Without a count, yanks the cell to the left and the\n\
176                 current cell. Paste with p.",
177    },
178    HelpEntry {
179        tags: &["x"],
180        category: HelpCategory::Normal,
181        summary: "Clear current cell",
182        detail: "Clears the content of the cell under the cursor. Undoable with u.",
183    },
184    HelpEntry {
185        tags: &["p"],
186        category: HelpCategory::Normal,
187        summary: "Paste below",
188        detail: "Paste the register contents below the current row (for row/block\nregisters) or into the cell below (for cell registers).\nFormula references are adjusted automatically.",
189    },
190    HelpEntry {
191        tags: &["P"],
192        category: HelpCategory::Normal,
193        summary: "Paste above",
194        detail: "Paste the register contents above the current row (for row/block\nregisters) or into the current cell (for cell registers).\nFormula references are adjusted automatically.",
195    },
196    HelpEntry {
197        tags: &["."],
198        category: HelpCategory::Normal,
199        summary: "Repeat last change",
200        detail: "Re-apply the last cell-mutating operation at the current cursor \
201                 position. Works after x, dd, d (visual), p, P, and any edit committed from \
202                 Insert mode (i/a/c + Esc or Enter). u and Ctrl-r do not affect \
203                 the repeat register.",
204    },
205    HelpEntry {
206        tags: &["u"],
207        category: HelpCategory::Normal,
208        summary: "Undo",
209        detail: "Undo the last cell edit. Supports multiple levels of undo.",
210    },
211    HelpEntry {
212        tags: &["Ctrl+R"],
213        category: HelpCategory::Normal,
214        summary: "Redo",
215        detail: "Redo the last undone edit.",
216    },
217    HelpEntry {
218        tags: &["Ctrl+D"],
219        category: HelpCategory::Normal,
220        summary: "Half page down",
221        detail: "Move the cursor down by half the visible page height.",
222    },
223    HelpEntry {
224        tags: &["Ctrl+U"],
225        category: HelpCategory::Normal,
226        summary: "Half page up",
227        detail: "Move the cursor up by half the visible page height.",
228    },
229    HelpEntry {
230        tags: &["Ctrl+F"],
231        category: HelpCategory::Normal,
232        summary: "Page down",
233        detail: "Move the cursor down by one full page.",
234    },
235    HelpEntry {
236        tags: &["Ctrl+B"],
237        category: HelpCategory::Normal,
238        summary: "Page up",
239        detail: "Move the cursor up by one full page.",
240    },
241    HelpEntry {
242        tags: &["Ctrl+E"],
243        category: HelpCategory::Normal,
244        summary: "Scroll viewport down one row",
245        detail: "Scroll the viewport down one row without moving the cursor.\n\
246                 If the cursor would scroll off the top, it stays pinned to\n\
247                 the top visible row.",
248    },
249    HelpEntry {
250        tags: &["Ctrl+Y"],
251        category: HelpCategory::Normal,
252        summary: "Scroll viewport up one row",
253        detail: "Scroll the viewport up one row without moving the cursor.\n\
254                 If the cursor would scroll off the bottom, it stays pinned\n\
255                 to the bottom visible row.",
256    },
257    HelpEntry {
258        tags: &["zz"],
259        category: HelpCategory::Normal,
260        summary: "Recenter viewport on cursor",
261        detail: "Scroll the viewport so the cursor sits at the vertical\n\
262                 center of the visible rows. Cursor position is unchanged.",
263    },
264    HelpEntry {
265        tags: &["zt"],
266        category: HelpCategory::Normal,
267        summary: "Scroll cursor to top of viewport",
268        detail: "Scroll the viewport so the cursor row becomes the top\n\
269                 visible row. Cursor position is unchanged.",
270    },
271    HelpEntry {
272        tags: &["zb"],
273        category: HelpCategory::Normal,
274        summary: "Scroll cursor to bottom of viewport",
275        detail: "Scroll the viewport so the cursor row becomes the bottom\n\
276                 visible row. Cursor position is unchanged.",
277    },
278    HelpEntry {
279        tags: &["H"],
280        category: HelpCategory::Normal,
281        summary: "Cursor to top of viewport",
282        detail: "Move the cursor to the topmost visible row, keeping the\n\
283                 current column. Viewport is unchanged.",
284    },
285    HelpEntry {
286        tags: &["M"],
287        category: HelpCategory::Normal,
288        summary: "Cursor to middle of viewport",
289        detail: "Move the cursor to the middle visible row, keeping the\n\
290                 current column. Viewport is unchanged.",
291    },
292    HelpEntry {
293        tags: &["L"],
294        category: HelpCategory::Normal,
295        summary: "Cursor to bottom of viewport",
296        detail: "Move the cursor to the bottommost visible row, keeping the\n\
297                 current column. Viewport is unchanged.",
298    },
299    HelpEntry {
300        tags: &["m", "mark"],
301        category: HelpCategory::Normal,
302        summary: "Set mark (m{a-z})",
303        detail: "After pressing m, the next lowercase letter records the\n\
304                 current cursor position as a named mark. Marks are\n\
305                 session-only. Jump back with '{a-z} (line-wise) or\n\
306                 `{a-z} (exact cell).",
307    },
308    HelpEntry {
309        tags: &["'"],
310        category: HelpCategory::Normal,
311        summary: "Jump to mark (line-wise)",
312        detail: "After pressing ', the next lowercase letter jumps the\n\
313                 cursor to the row of the matching mark, at column A.\n\
314                 If the mark is unset, status reports `E20: Mark not set`.",
315    },
316    HelpEntry {
317        tags: &["`", "backtick"],
318        category: HelpCategory::Normal,
319        summary: "Jump to mark (exact cell)",
320        detail: "After pressing `, the next lowercase letter jumps the\n\
321                 cursor to the exact cell of the matching mark.\n\
322                 If the mark is unset, status reports `E20: Mark not set`.",
323    },
324    HelpEntry {
325        tags: &["Ctrl+O"],
326        category: HelpCategory::Normal,
327        summary: "Jump back in jump list",
328        detail: "Move backward through the jump list, which records cursor\n\
329                 positions across long-distance motions (gg, G, marks,\n\
330                 search). Pairs with Ctrl+I / Tab to jump forward. The\n\
331                 jump list is capped at 100 entries.",
332    },
333    HelpEntry {
334        tags: &["Ctrl+I", "Tab"],
335        category: HelpCategory::Normal,
336        summary: "Jump forward in jump list",
337        detail: "Move forward through the jump list. Pairs with Ctrl+O\n\
338                 to jump back. Mid-stack jumps truncate the forward history.",
339    },
340    HelpEntry {
341        tags: &["{"],
342        category: HelpCategory::Normal,
343        summary: "Block jump up in column",
344        detail: "Jump to the previous block boundary in the current column,\n\
345                 mirroring vim's paragraph motion. From a non-empty cell,\n\
346                 lands on the first empty row above the current block;\n\
347                 from an empty cell, lands on the next non-empty row above.",
348    },
349    HelpEntry {
350        tags: &["}"],
351        category: HelpCategory::Normal,
352        summary: "Block jump down in column",
353        detail: "Jump to the next block boundary in the current column,\n\
354                 mirroring vim's paragraph motion. From a non-empty cell,\n\
355                 lands on the first empty row below the current block;\n\
356                 from an empty cell, lands on the next non-empty row below.",
357    },
358    HelpEntry {
359        tags: &["*"],
360        category: HelpCategory::Normal,
361        summary: "Search current cell value forward",
362        detail: "Treat the current cell's displayed value as the search\n\
363                 pattern and jump to the next matching cell. The pattern\n\
364                 is stored, so n / N continue stepping through matches.",
365    },
366    HelpEntry {
367        tags: &["#"],
368        category: HelpCategory::Normal,
369        summary: "Search current cell value backward",
370        detail: "Treat the current cell's displayed value as the search\n\
371                 pattern and jump to the previous matching cell. The pattern\n\
372                 is stored, so n / N continue stepping through matches.",
373    },
374    HelpEntry {
375        tags: &["gv"],
376        category: HelpCategory::Normal,
377        summary: "Re-enter previous visual selection",
378        detail: "Re-enter Visual mode with the same anchor, cursor, and\n\
379                 visual kind (Character / Line / Block) as the last\n\
380                 selection. No-op if no previous selection exists.",
381    },
382    HelpEntry {
383        tags: &["c"],
384        category: HelpCategory::Normal,
385        summary: "Change cell",
386        detail: "Clear the current cell and enter Insert mode to type its new\n\
387                 content. Equivalent to x followed by i.",
388    },
389    HelpEntry {
390        tags: &["V"],
391        category: HelpCategory::Normal,
392        summary: "Enter Visual Line mode",
393        detail: "Start full-row (line-wise) visual selection from the\n\
394                 current row. Use j/k to extend; press d/y/c to act on the\n\
395                 selected rows.",
396    },
397    HelpEntry {
398        tags: &["i", "a"],
399        category: HelpCategory::Normal,
400        summary: "Enter Insert mode",
401        detail: "Switch to Insert mode to edit the current cell.\ni places the cursor at the end of existing content.\na behaves the same as i in Cell.",
402    },
403    HelpEntry {
404        tags: &["o"],
405        category: HelpCategory::Normal,
406        summary: "Enter Insert mode (new line)",
407        detail: "Switch to Insert mode. In Cell, behaves the same as i\n(there are no multi-line cells).",
408    },
409    HelpEntry {
410        tags: &["Enter"],
411        category: HelpCategory::Normal,
412        summary: "Edit cell",
413        detail: "Enter Insert mode to edit the current cell. Same as i.",
414    },
415    HelpEntry {
416        tags: &["v"],
417        category: HelpCategory::Normal,
418        summary: "Enter Visual mode",
419        detail: "Start visual selection from the current cell. Use h/j/k/l to\nextend the selection. Press d to delete or y to yank.",
420    },
421    HelpEntry {
422        tags: &["Ctrl+V"],
423        category: HelpCategory::Normal,
424        summary: "Enter Visual Block mode",
425        detail: "Start block (rectangular) selection from the current cell.\nUse h/j/k/l to extend. Press d to delete or y to yank.",
426    },
427    HelpEntry {
428        tags: &["/"],
429        category: HelpCategory::Normal,
430        summary: "Search forward",
431        detail: "Open the forward-search prompt. Type a pattern and press Enter to\nfind the next cell whose value contains the pattern.\nCase-insensitive. Use n / N to step through matches.",
432    },
433    HelpEntry {
434        tags: &["?"],
435        category: HelpCategory::Normal,
436        summary: "Search backward",
437        detail: "Open the backward-search prompt. Type a pattern and press Enter\nto find the previous cell whose value contains the pattern.\nCase-insensitive. Use n / N to step through matches.",
438    },
439    HelpEntry {
440        tags: &["n"],
441        category: HelpCategory::Normal,
442        summary: "Next search match",
443        detail: "Jump to the next cell matching the last search pattern.",
444    },
445    HelpEntry {
446        tags: &["N"],
447        category: HelpCategory::Normal,
448        summary: "Previous search match",
449        detail: "Jump to the previous cell matching the last search pattern.",
450    },
451    HelpEntry {
452        tags: &["f"],
453        category: HelpCategory::Normal,
454        summary: "Find char in row (forward)",
455        detail: "After f, the next keypress is the target character. The cursor\njumps to the next non-empty cell in the current row whose displayed\nvalue starts with that character (case-insensitive).\nUse ; to repeat and , to repeat reversed.",
456    },
457    HelpEntry {
458        tags: &["F"],
459        category: HelpCategory::Normal,
460        summary: "Find char in row (backward)",
461        detail: "Like f, but searches the current row to the left of the cursor.",
462    },
463    HelpEntry {
464        tags: &[";"],
465        category: HelpCategory::Normal,
466        summary: "Repeat last find",
467        detail: "Repeat the last f / F find in the same direction.",
468    },
469    HelpEntry {
470        tags: &[","],
471        category: HelpCategory::Normal,
472        summary: "Repeat last find reversed",
473        detail: "Repeat the last f / F find in the opposite direction.",
474    },
475    HelpEntry {
476        tags: &["~", "tilde"],
477        category: HelpCategory::Normal,
478        summary: "Toggle case of first character",
479        detail: "Toggle the case of the first character of the current cell's value\n\
480                 and advance the cursor one column to the right (vim `~` semantics\n\
481                 scoped to one cell). No-op on formula cells.",
482    },
483    HelpEntry {
484        tags: &["guu"],
485        category: HelpCategory::Normal,
486        summary: "Lowercase entire cell",
487        detail: "Convert every character in the current cell's value to lowercase.\n\
488                 No-op on formula cells. Undoable with u.",
489    },
490    HelpEntry {
491        tags: &["gUU"],
492        category: HelpCategory::Normal,
493        summary: "Uppercase entire cell",
494        detail: "Convert every character in the current cell's value to uppercase.\n\
495                 No-op on formula cells. Undoable with u.",
496    },
497    HelpEntry {
498        tags: &["g~~"],
499        category: HelpCategory::Normal,
500        summary: "Toggle case of entire cell",
501        detail: "Toggle the case of every character in the current cell's value\n\
502                 (uppercase ↔ lowercase). No-op on formula cells. Undoable with u.",
503    },
504    HelpEntry {
505        tags: &["Ctrl+A"],
506        category: HelpCategory::Normal,
507        summary: "Increment number under cursor ([count]Ctrl+A)",
508        detail: "Add 1 (or [count]) to the number stored in the current cell.\n\
509                 Dependent formula cells are re-evaluated automatically.\n\
510                 No-op if the cell contains a formula (shows an error message)\n\
511                 or non-numeric text. Repeatable with '.'.",
512    },
513    HelpEntry {
514        tags: &["Ctrl+X"],
515        category: HelpCategory::Normal,
516        summary: "Decrement number under cursor ([count]Ctrl+X)",
517        detail: "Subtract 1 (or [count]) from the number stored in the current cell.\n\
518                 Dependent formula cells are re-evaluated automatically.\n\
519                 No-op if the cell contains a formula (shows an error message)\n\
520                 or non-numeric text. Repeatable with '.'.",
521    },
522];
523
524pub static INSERT_ENTRIES: &[HelpEntry] = &[
525    HelpEntry {
526        tags: &["Esc"],
527        category: HelpCategory::Insert,
528        summary: "Confirm edit, return to Normal",
529        detail: "Saves the current cell content and returns to Normal mode.",
530    },
531    HelpEntry {
532        tags: &["Enter-insert"],
533        category: HelpCategory::Insert,
534        summary: "Confirm edit and move down",
535        detail: "Saves the current cell content and returns to Normal mode.\nIn Insert mode, Enter confirms the edit (same as Esc).",
536    },
537    HelpEntry {
538        tags: &["Backspace"],
539        category: HelpCategory::Insert,
540        summary: "Delete character before cursor",
541        detail: "Deletes the character to the left of the cursor in the cell\nedit buffer.",
542    },
543    HelpEntry {
544        tags: &["Delete"],
545        category: HelpCategory::Insert,
546        summary: "Delete character at cursor",
547        detail: "Deletes the character at the cursor position in the cell\nedit buffer.",
548    },
549    HelpEntry {
550        tags: &["Left-insert", "Right-insert"],
551        category: HelpCategory::Insert,
552        summary: "Move cursor within cell",
553        detail: "Arrow keys move the cursor left/right within the cell edit\nbuffer during Insert mode.",
554    },
555    HelpEntry {
556        tags: &["Home"],
557        category: HelpCategory::Insert,
558        summary: "Move to start of cell",
559        detail: "Move the cursor to the beginning of the cell edit buffer.",
560    },
561    HelpEntry {
562        tags: &["End"],
563        category: HelpCategory::Insert,
564        summary: "Move to end of cell",
565        detail: "Move the cursor to the end of the cell edit buffer.",
566    },
567];
568
569pub static VISUAL_ENTRIES: &[HelpEntry] = &[
570    HelpEntry {
571        tags: &["v-visual"],
572        category: HelpCategory::Visual,
573        summary: "Enter Visual mode",
574        detail: "Start visual selection from Normal mode. The anchor is set at\nthe current cursor position.",
575    },
576    HelpEntry {
577        tags: &["Ctrl+V-visual"],
578        category: HelpCategory::Visual,
579        summary: "Enter Visual Block mode",
580        detail: "Start rectangular block selection from Normal mode.",
581    },
582    HelpEntry {
583        tags: &["count-visual", "[count]-visual"],
584        category: HelpCategory::Visual,
585        summary: "Count prefix in Visual mode ([count]motion)",
586        detail: "Type digits before a motion key (h j k l) to extend the\n\
587                 selection by that many cells. For example, v then 3l selects\n\
588                 the current cell plus 3 more to the right; 5j extends the\n\
589                 selection 5 rows down.",
590    },
591    HelpEntry {
592        tags: &["d-visual"],
593        category: HelpCategory::Visual,
594        summary: "Delete selection",
595        detail: "Clear all cells in the visual selection. The contents are\nstored in the register. Returns to Normal mode.",
596    },
597    HelpEntry {
598        tags: &["y-visual"],
599        category: HelpCategory::Visual,
600        summary: "Yank selection",
601        detail: "Copy all cells in the visual selection to the register.\nReturns to Normal mode.",
602    },
603    HelpEntry {
604        tags: &["Esc-visual"],
605        category: HelpCategory::Visual,
606        summary: "Cancel selection",
607        detail: "Exit Visual mode and return to Normal mode without\nmodifying any cells.",
608    },
609    HelpEntry {
610        tags: &["u-visual"],
611        category: HelpCategory::Visual,
612        summary: "Lowercase selection",
613        detail: "Convert every character in every selected cell to lowercase.\n\
614                 Formula cells in the selection are skipped. Undoable with u\n\
615                 after returning to Normal mode.",
616    },
617    HelpEntry {
618        tags: &["U-visual"],
619        category: HelpCategory::Visual,
620        summary: "Uppercase selection",
621        detail: "Convert every character in every selected cell to uppercase.\n\
622                 Formula cells in the selection are skipped. Undoable with u\n\
623                 after returning to Normal mode.",
624    },
625    HelpEntry {
626        tags: &["~-visual"],
627        category: HelpCategory::Visual,
628        summary: "Toggle case of selection",
629        detail: "Toggle the case of every character in every selected cell\n\
630                 (uppercase ↔ lowercase). Formula cells in the selection are\n\
631                 skipped. Undoable with u after returning to Normal mode.",
632    },
633];
634
635pub static COMMAND_ENTRIES: &[HelpEntry] = &[
636    HelpEntry {
637        tags: &[":w", ":write"],
638        category: HelpCategory::Command,
639        summary: "Save file",
640        detail: "Write the current sheet to disk. If no filename has been set,\nuse :w <path> to specify one.\n\nIf the sheet contains formulas and you save as CSV/TSV,\nCell will warn you. Use :w file.cell to preserve formulas,\nor :w! to force save as CSV (formulas become values).\n\nIf the active delimiter (see :set delimiter) does not match\nthe file extension convention, Cell will also warn you.\nUse :w! to override.",
641    },
642    HelpEntry {
643        tags: &[":w!"],
644        category: HelpCategory::Command,
645        summary: "Force save",
646        detail: "Write the current sheet to disk, bypassing both the\nformula-flatten warning and the non-standard-delimiter warning.",
647    },
648    HelpEntry {
649        tags: &[":q", ":quit"],
650        category: HelpCategory::Command,
651        summary: "Quit",
652        detail: "Exit Cell. Fails if there are unsaved changes.\nUse :q! to discard changes, or :wq to save and quit.",
653    },
654    HelpEntry {
655        tags: &[":q!"],
656        category: HelpCategory::Command,
657        summary: "Force quit",
658        detail: "Exit Cell without saving. All unsaved changes are discarded.",
659    },
660    HelpEntry {
661        tags: &[":wq"],
662        category: HelpCategory::Command,
663        summary: "Save and quit",
664        detail: "Write the current sheet to disk, then exit Cell.",
665    },
666    HelpEntry {
667        tags: &[":e", ":edit"],
668        category: HelpCategory::Command,
669        summary: "Open file",
670        detail: "Open a file for editing.\nUsage: :e <path>\n\nSupported formats: CSV, TSV, .cell (native format).",
671    },
672    HelpEntry {
673        tags: &[":sort"],
674        category: HelpCategory::Command,
675        summary: "Sort by column",
676        detail: "Sort all rows by the values in a column.\nUsage: :sort <column> [asc|desc]\n\nExamples:\n  :sort A        Sort by column A ascending\n  :sort B desc   Sort by column B descending",
677    },
678    HelpEntry {
679        tags: &[":set delimiter", "--delimiter", "delimiter"],
680        category: HelpCategory::Command,
681        summary: "Set the field delimiter",
682        detail: "Set the delimiter character used when reading or saving\nCSV/TSV files.\n\nUsage (ex-command):  :set delimiter=|\n                     :set delimiter=;\nUsage (CLI flag):    cell data.psv --delimiter '|'\n\nValid delimiters: any single printable ASCII character that\nis not a letter, digit, or double-quote (e.g. | ; , \\t).\n\nThe delimiter is auto-detected from file content on open\nwhen the --delimiter flag is not provided and the extension\nis not .tsv. Use --delimiter to override detection.\n\n:set delimiter only affects the next save — it does not\nre-parse the currently loaded file. To reload with a new\ndelimiter, close and reopen the file with --delimiter.",
683    },
684    HelpEntry {
685        tags: &[":help"],
686        category: HelpCategory::Command,
687        summary: "Open help",
688        detail: "Show this help screen.\nUsage: :help [topic]\n\n:help          Show table of contents\n:help dd       Show help for the dd command\n:help :w       Show help for the :w command\n:help SUM      Show help for the SUM formula",
689    },
690];
691
692pub static FORMULA_ENTRIES: &[HelpEntry] = &[
693    HelpEntry {
694        tags: &["SUM"],
695        category: HelpCategory::Formula,
696        summary: "Sum values in a range",
697        detail: "Returns the sum of all numeric values in the range.\nNon-numeric cells are ignored.\n\nUsage: =SUM(A1:A10)\n       =SUM(B2:D5)",
698    },
699    HelpEntry {
700        tags: &["AVERAGE"],
701        category: HelpCategory::Formula,
702        summary: "Average of values in a range",
703        detail: "Returns the arithmetic mean of all numeric values in the range.\nNon-numeric cells are ignored. Returns #DIV/0! if no numeric\nvalues are found.\n\nUsage: =AVERAGE(A1:A10)",
704    },
705    HelpEntry {
706        tags: &["COUNT"],
707        category: HelpCategory::Formula,
708        summary: "Count numeric cells in a range",
709        detail: "Returns the number of cells containing numeric values in\nthe range. Non-numeric cells are not counted.\n\nUsage: =COUNT(A1:A10)",
710    },
711    HelpEntry {
712        tags: &["MIN"],
713        category: HelpCategory::Formula,
714        summary: "Minimum value in a range",
715        detail: "Returns the smallest numeric value in the range.\nNon-numeric cells are ignored. Returns 0 if no numeric\nvalues are found.\n\nUsage: =MIN(A1:A10)",
716    },
717    HelpEntry {
718        tags: &["MAX"],
719        category: HelpCategory::Formula,
720        summary: "Maximum value in a range",
721        detail: "Returns the largest numeric value in the range.\nNon-numeric cells are ignored. Returns 0 if no numeric\nvalues are found.\n\nUsage: =MAX(A1:A10)",
722    },
723    HelpEntry {
724        tags: &["IF"],
725        category: HelpCategory::Formula,
726        summary: "Conditional expression",
727        detail: "Returns one value if a condition is true, another if false.\n\nUsage: =IF(condition, value_if_true, value_if_false)\n\nExamples:\n  =IF(A1>10, \"big\", \"small\")\n  =IF(B2, C2, D2)",
728    },
729];
730
731pub static MOUSE_ENTRIES: &[HelpEntry] = &[
732    HelpEntry {
733        tags: &["mouse", ":set mouse"],
734        category: HelpCategory::Mouse,
735        summary: "Enable / disable mouse support",
736        detail: "Mouse support is OFF by default. Toggle at runtime:\n\
737                 \n\
738                 :set mouse on        Enable mouse capture.\n\
739                 :set mouse off       Disable mouse capture.\n\
740                 :set mouse toggle    Flip the current state.\n\
741                 \n\
742                 When mouse mode is on, the terminal stops doing native\n\
743                 text selection. Hold your terminal's bypass modifier to\n\
744                 fall back to native selection for copy:\n\
745                 \n\
746                 - Linux & Windows Terminal: Shift\n\
747                 - macOS Terminal.app and iTerm2: Option/Alt\n\
748                 - tmux/screen: see your terminal's docs",
749    },
750    HelpEntry {
751        tags: &["mouse-click", "click"],
752        category: HelpCategory::Mouse,
753        summary: "Left-click moves the cursor",
754        detail: "Left-click on a grid cell moves the cursor there. From\n\
755                 Insert mode the in-progress edit is committed first;\n\
756                 from Command mode the prompt is cancelled; from Visual\n\
757                 the selection is exited.\n\
758                 \n\
759                 Click on the formula bar, status bar, or padding around\n\
760                 the grid is a no-op and never commits an edit.",
761    },
762    HelpEntry {
763        tags: &["mouse-drag", "drag"],
764        category: HelpCategory::Mouse,
765        summary: "Click + drag selects a range",
766        detail: "Drag inside the grid: enters Visual mode and extends the\n\
767                 selection from the click cell to the current cell.\n\
768                 \n\
769                 Drag on a column header: selects whole columns.\n\
770                 Drag on a row header: selects whole rows.\n\
771                 \n\
772                 Dragging a cell selection past the visible edge auto-\n\
773                 scrolls the viewport one row/column per drag event.",
774    },
775    HelpEntry {
776        tags: &["mouse-scroll", "scroll-wheel", "wheel"],
777        category: HelpCategory::Mouse,
778        summary: "Scroll wheel scrolls the viewport",
779        detail: "The scroll wheel scrolls the viewport up or down by 3\n\
780                 rows. The cursor does not move, even if it scrolls out\n\
781                 of view (matches Vim's mouse behaviour).\n\
782                 \n\
783                 Horizontal scroll (Shift+wheel on most terminals)\n\
784                 scrolls the viewport left or right when the terminal\n\
785                 emits ScrollLeft / ScrollRight events.",
786    },
787    HelpEntry {
788        tags: &["mouse-double-click", "double-click", "edit-cell"],
789        category: HelpCategory::Mouse,
790        summary: "Double-click enters Insert mode",
791        detail: "Two left-clicks on the same cell within ~400ms enter\n\
792                 Insert mode on that cell. A second click on a different\n\
793                 cell, or after the threshold, is treated as a fresh\n\
794                 single click.",
795    },
796    HelpEntry {
797        tags: &["mouse-bypass", "shift-click"],
798        category: HelpCategory::Mouse,
799        summary: "Shift+click bypasses mouse capture",
800        detail: "Holding Shift while clicking is treated as a no-op by\n\
801                 cell, allowing the terminal's native text selection to\n\
802                 take over. Use this to copy a cell value or formula\n\
803                 string out to your system clipboard. (On macOS\n\
804                 Terminal.app and iTerm2 the bypass modifier is\n\
805                 typically Option/Alt — check your terminal settings.)",
806    },
807];