Skip to main content

zsh/ported/zle/
comp_h.rs

1//! `comp.h` port — completion descriptor types + flag constants.
2//!
3//! Port of `Src/Zle/comp.h`. Canonical home for the new-style
4//! completion machinery (compsys / compadd / addmatches / etc.) —
5//! distinct from the legacy `compctl.h` machinery (which lives in
6//! `compctl_h.rs`).
7//!
8//! C source: 10 typedefs (`Cmatcher`/`Cmlist`/`Cpattern`/`Menuinfo`/
9//! `Cexpl`/`Cmgroup`/`Cmatch`/`Cline`/`Aminfo`/`Cadata`/`Cldata`/
10//! `Chdata`), 13 structs (`cexpl`/`cmgroup`/`cmatch`/`cmlist`/
11//! `cmatcher`/`cpattern`/`cline`/`aminfo`/`menuinfo`/`ccmakedat`/
12//! `chdata`/`cadata`/`cldata`), 1 enum (`cpat`), and ~80 flag
13//! constants. 0 functions.
14//!
15//! All UPPERCASE C constants (CGF_*, CMF_*, CLF_*, CAF_*, FC_*,
16//! CP_*, CPN_*) preserved verbatim per the macro casing rule.
17//! Struct names match C casing (Cexpl, Cmgroup, Cmatch, etc.) with
18//! `#[allow(non_camel_case_types)]` silencing the convention warning.
19
20// ---------------------------------------------------------------------------
21// Group-flag constants (c:85-95) — flags on `cmgroup.flags`.
22// ---------------------------------------------------------------------------
23
24
25// --- AUTO: cross-zle hoisted-fn use glob ---
26#[allow(unused_imports)]
27#[allow(unused_imports)]
28use crate::ported::zle::zle_main::*;
29#[allow(unused_imports)]
30use crate::ported::zle::zle_misc::*;
31#[allow(unused_imports)]
32use crate::ported::zle::zle_hist::*;
33#[allow(unused_imports)]
34use crate::ported::zle::zle_move::*;
35#[allow(unused_imports)]
36use crate::ported::zle::zle_word::*;
37#[allow(unused_imports)]
38use crate::ported::zle::zle_params::*;
39#[allow(unused_imports)]
40use crate::ported::zle::zle_vi::*;
41#[allow(unused_imports)]
42use crate::ported::zle::zle_utils::*;
43#[allow(unused_imports)]
44use crate::ported::zle::zle_refresh::*;
45#[allow(unused_imports)]
46use crate::ported::zle::zle_tricky::*;
47#[allow(unused_imports)]
48use crate::ported::zle::textobjects::*;
49#[allow(unused_imports)]
50use crate::ported::zle::deltochar::*;
51
52pub const CGF_NOSORT:  i32 = 1;                                          // c:85
53pub const CGF_LINES:   i32 = 2;                                          // c:86
54pub const CGF_HASDL:   i32 = 4;                                          // c:87
55pub const CGF_UNIQALL: i32 = 8;                                          // c:88
56pub const CGF_UNIQCON: i32 = 16;                                         // c:89
57pub const CGF_PACKED:  i32 = 32;                                         // c:90
58pub const CGF_ROWS:    i32 = 64;                                         // c:91
59pub const CGF_FILES:   i32 = 128;                                        // c:92
60pub const CGF_MATSORT: i32 = 256;                                        // c:93
61pub const CGF_NUMSORT: i32 = 512;                                        // c:94
62pub const CGF_REVSORT: i32 = 1024;                                       // c:95
63
64// ---------------------------------------------------------------------------
65// Match-flag constants (c:127-143) — flags on `cmatch.flags`.
66// ---------------------------------------------------------------------------
67
68pub const CMF_FILE:     i32 = 1 <<  0;                                   // c:127
69pub const CMF_REMOVE:   i32 = 1 <<  1;                                   // c:128
70pub const CMF_ISPAR:    i32 = 1 <<  2;                                   // c:129
71pub const CMF_PARBR:    i32 = 1 <<  3;                                   // c:130
72pub const CMF_PARNEST:  i32 = 1 <<  4;                                   // c:131
73pub const CMF_NOLIST:   i32 = 1 <<  5;                                   // c:132
74pub const CMF_DISPLINE: i32 = 1 <<  6;                                   // c:133
75pub const CMF_HIDE:     i32 = 1 <<  7;                                   // c:134
76pub const CMF_NOSPACE:  i32 = 1 <<  8;                                   // c:135
77pub const CMF_PACKED:   i32 = 1 <<  9;                                   // c:136
78pub const CMF_ROWS:     i32 = 1 << 10;                                   // c:137
79pub const CMF_MULT:     i32 = 1 << 11;                                   // c:138
80pub const CMF_FMULT:    i32 = 1 << 12;                                   // c:139
81pub const CMF_ALL:      i32 = 1 << 13;                                   // c:140
82pub const CMF_DUMMY:    i32 = 1 << 14;                                   // c:141
83pub const CMF_MORDER:   i32 = 1 << 15;                                   // c:142
84pub const CMF_DELETE:   i32 = 1 << 16;                                   // c:143
85
86// ---------------------------------------------------------------------------
87// Cmatcher flag constants (c:172-178) — flags on `cmatcher.flags`.
88//
89// NOTE: C uses the same `CMF_*` prefix for both `cmatch.flags` and
90// `cmatcher.flags`. The values are different (cmatcher uses
91// 1/2/4/8 vs cmatch's bitfields) but the names overlap (CMF_LINE
92// here is 1, while there's no CMF_LINE in cmatch's set). Rust
93// preserves both verbatim — the per-struct dispatch context tells
94// callers which set applies.
95// ---------------------------------------------------------------------------
96
97pub const CMF_LINE:  i32 = 1;                                            // c:172
98pub const CMF_LEFT:  i32 = 2;                                            // c:174
99pub const CMF_RIGHT: i32 = 4;                                            // c:176
100pub const CMF_INTER: i32 = 8;                                            // c:178
101
102// ---------------------------------------------------------------------------
103// Cpattern type discriminators (c:184-190).
104// ---------------------------------------------------------------------------
105
106/// Port of `enum { CPAT_CCLASS, ... }` from `Src/Zle/comp.h:184-190`.
107/// C uses an anonymous int-constant enum — Rust ports as `pub const`s
108/// to avoid a Rust-only enum type. The discriminator drives
109/// `freecpattern()` and `cpattern.tp` dispatch (see `Cpattern` below).
110pub const CPAT_CCLASS: i32 = 0;                                          // c:185
111pub const CPAT_NCLASS: i32 = 1;                                          // c:186
112pub const CPAT_EQUIV:  i32 = 2;                                          // c:187
113pub const CPAT_ANY:    i32 = 3;                                          // c:188
114pub const CPAT_CHAR:   i32 = 4;                                          // c:189
115
116// ---------------------------------------------------------------------------
117// Cline flag constants (c:259-267) — flags on `cline.flags`.
118// ---------------------------------------------------------------------------
119
120pub const CLF_MISS:    i32 = 1;                                          // c:259
121pub const CLF_DIFF:    i32 = 2;                                          // c:260
122pub const CLF_SUF:     i32 = 4;                                          // c:261
123pub const CLF_MID:     i32 = 8;                                          // c:262
124pub const CLF_NEW:     i32 = 16;                                         // c:263
125pub const CLF_LINE:    i32 = 32;                                         // c:264
126pub const CLF_JOIN:    i32 = 64;                                         // c:265
127pub const CLF_MATCHED: i32 = 128;                                        // c:266
128pub const CLF_SKIP:    i32 = 256;                                        // c:267
129
130// ---------------------------------------------------------------------------
131// compadd / addmatches() flag constants (c:299-309).
132// ---------------------------------------------------------------------------
133
134pub const CAF_QUOTE:   i32 = 1;                                          // c:299
135pub const CAF_NOSORT:  i32 = 2;                                          // c:300
136pub const CAF_MATCH:   i32 = 4;                                          // c:301
137pub const CAF_UNIQCON: i32 = 8;                                          // c:302
138pub const CAF_UNIQALL: i32 = 16;                                         // c:303
139pub const CAF_ARRAYS:  i32 = 32;                                         // c:304
140pub const CAF_KEYS:    i32 = 64;                                         // c:305
141pub const CAF_ALL:     i32 = 128;                                        // c:306
142pub const CAF_MATSORT: i32 = 256;                                        // c:307
143pub const CAF_NUMSORT: i32 = 512;                                        // c:308
144pub const CAF_REVSORT: i32 = 1024;                                       // c:309
145
146// ---------------------------------------------------------------------------
147// Fromcomp flags (c:359-360).
148// ---------------------------------------------------------------------------
149
150pub const FC_LINE:   i32 = 1;                                            // c:359
151pub const FC_INWORD: i32 = 2;                                            // c:360
152
153// ---------------------------------------------------------------------------
154// Special-parameter index constants — `comprpms` / "real params"
155// (c:364-386). For each parameter there's a `CPN_*` index and a
156// `CP_*` bitmask `(1 << CPN_*)`.
157// ---------------------------------------------------------------------------
158
159pub const CPN_WORDS:     i32 = 0;                                        // c:364
160pub const CP_WORDS:      u32 = 1 << CPN_WORDS;                           // c:365
161pub const CPN_REDIRS:    i32 = 1;                                        // c:366
162pub const CP_REDIRS:     u32 = 1 << CPN_REDIRS;                          // c:367
163pub const CPN_CURRENT:   i32 = 2;                                        // c:368
164pub const CP_CURRENT:    u32 = 1 << CPN_CURRENT;                         // c:369
165pub const CPN_PREFIX:    i32 = 3;                                        // c:370
166pub const CP_PREFIX:     u32 = 1 << CPN_PREFIX;                          // c:371
167pub const CPN_SUFFIX:    i32 = 4;                                        // c:372
168pub const CP_SUFFIX:     u32 = 1 << CPN_SUFFIX;                          // c:373
169pub const CPN_IPREFIX:   i32 = 5;                                        // c:374
170pub const CP_IPREFIX:    u32 = 1 << CPN_IPREFIX;                         // c:375
171pub const CPN_ISUFFIX:   i32 = 6;                                        // c:376
172pub const CP_ISUFFIX:    u32 = 1 << CPN_ISUFFIX;                         // c:377
173pub const CPN_QIPREFIX:  i32 = 7;                                        // c:378
174pub const CP_QIPREFIX:   u32 = 1 << CPN_QIPREFIX;                        // c:379
175pub const CPN_QISUFFIX:  i32 = 8;                                        // c:380
176pub const CP_QISUFFIX:   u32 = 1 << CPN_QISUFFIX;                        // c:381
177pub const CPN_COMPSTATE: i32 = 9;                                        // c:382
178pub const CP_COMPSTATE:  u32 = 1 << CPN_COMPSTATE;                       // c:383
179
180/// Port of `#define CP_REALPARAMS` from `Src/Zle/comp.h:385`. Total
181/// number of "real" comp parameters.
182pub const CP_REALPARAMS: i32 = 10;                                       // c:385
183
184/// Port of `#define CP_ALLREALS` from `Src/Zle/comp.h:386`. Mask
185/// covering every CP_* "real" param flag (bits 0..9 set).
186pub const CP_ALLREALS: u32 = 0x3ff;                                      // c:386
187
188// ---------------------------------------------------------------------------
189// Special-parameter index constants — `compkpms` / "key params"
190// (c:389-442).
191// ---------------------------------------------------------------------------
192
193pub const CPN_NMATCHES:   i32 = 0;                                       // c:389
194pub const CP_NMATCHES:    u32 = 1 << CPN_NMATCHES;                       // c:390
195pub const CPN_CONTEXT:    i32 = 1;                                       // c:391
196pub const CP_CONTEXT:     u32 = 1 << CPN_CONTEXT;                        // c:392
197pub const CPN_PARAMETER:  i32 = 2;                                       // c:393
198pub const CP_PARAMETER:   u32 = 1 << CPN_PARAMETER;                      // c:394
199pub const CPN_REDIRECT:   i32 = 3;                                       // c:395
200pub const CP_REDIRECT:    u32 = 1 << CPN_REDIRECT;                       // c:396
201pub const CPN_QUOTE:      i32 = 4;                                       // c:397
202pub const CP_QUOTE:       u32 = 1 << CPN_QUOTE;                          // c:398
203pub const CPN_QUOTING:    i32 = 5;                                       // c:399
204pub const CP_QUOTING:     u32 = 1 << CPN_QUOTING;                        // c:400
205pub const CPN_RESTORE:    i32 = 6;                                       // c:401
206pub const CP_RESTORE:     u32 = 1 << CPN_RESTORE;                        // c:402
207pub const CPN_LIST:       i32 = 7;                                       // c:403
208pub const CP_LIST:        u32 = 1 << CPN_LIST;                           // c:404
209pub const CPN_INSERT:     i32 = 8;                                       // c:405
210pub const CP_INSERT:      u32 = 1 << CPN_INSERT;                         // c:406
211pub const CPN_EXACT:      i32 = 9;                                       // c:407
212pub const CP_EXACT:       u32 = 1 << CPN_EXACT;                          // c:408
213pub const CPN_EXACTSTR:   i32 = 10;                                      // c:409
214pub const CP_EXACTSTR:    u32 = 1 << CPN_EXACTSTR;                       // c:410
215pub const CPN_PATMATCH:   i32 = 11;                                      // c:411
216pub const CP_PATMATCH:    u32 = 1 << CPN_PATMATCH;                       // c:412
217pub const CPN_PATINSERT:  i32 = 12;                                      // c:413
218pub const CP_PATINSERT:   u32 = 1 << CPN_PATINSERT;                      // c:414
219pub const CPN_UNAMBIG:    i32 = 13;                                      // c:415
220pub const CP_UNAMBIG:     u32 = 1 << CPN_UNAMBIG;                        // c:416
221pub const CPN_UNAMBIGC:   i32 = 14;                                      // c:417
222pub const CP_UNAMBIGC:    u32 = 1 << CPN_UNAMBIGC;                       // c:418
223pub const CPN_UNAMBIGP:   i32 = 15;                                      // c:419
224pub const CP_UNAMBIGP:    u32 = 1 << CPN_UNAMBIGP;                       // c:420
225pub const CPN_INSERTP:    i32 = 16;                                      // c:421
226pub const CP_INSERTP:     u32 = 1 << CPN_INSERTP;                        // c:422
227pub const CPN_LISTMAX:    i32 = 17;                                      // c:423
228pub const CP_LISTMAX:     u32 = 1 << CPN_LISTMAX;                        // c:424
229pub const CPN_LASTPROMPT: i32 = 18;                                      // c:425
230pub const CP_LASTPROMPT:  u32 = 1 << CPN_LASTPROMPT;                     // c:426
231pub const CPN_TOEND:      i32 = 19;                                      // c:427
232pub const CP_TOEND:       u32 = 1 << CPN_TOEND;                          // c:428
233pub const CPN_OLDLIST:    i32 = 20;                                      // c:429
234pub const CP_OLDLIST:     u32 = 1 << CPN_OLDLIST;                        // c:430
235pub const CPN_OLDINS:     i32 = 21;                                      // c:431
236pub const CP_OLDINS:      u32 = 1 << CPN_OLDINS;                         // c:432
237pub const CPN_VARED:      i32 = 22;                                      // c:433
238pub const CP_VARED:       u32 = 1 << CPN_VARED;                          // c:434
239pub const CPN_LISTLINES:  i32 = 23;                                      // c:435
240pub const CP_LISTLINES:   u32 = 1 << CPN_LISTLINES;                      // c:436
241pub const CPN_QUOTES:     i32 = 24;                                      // c:437
242pub const CP_QUOTES:      u32 = 1 << CPN_QUOTES;                         // c:438
243pub const CPN_IGNORED:    i32 = 25;                                      // c:439
244pub const CP_IGNORED:     u32 = 1 << CPN_IGNORED;                        // c:440
245
246/// Port of `#define CP_KEYPARAMS` from `Src/Zle/comp.h:442`. Total
247/// number of "key" comp parameters.
248pub const CP_KEYPARAMS: i32 = 26;                                        // c:442
249
250/// Port of `#define CP_ALLKEYS` from `Src/Zle/comp.h:443`. Mask
251/// covering every CP_* "key" param flag (bits 0..25 set).
252pub const CP_ALLKEYS: u32 = 0x3ffffff;                                   // c:443
253
254// ---------------------------------------------------------------------------
255// Hook indexes (c:447-451).
256// ---------------------------------------------------------------------------
257
258pub const INSERTMATCHHOOK_OFFSET:     usize = 0;                         // c:447
259pub const MENUSTARTHOOK_OFFSET:       usize = 1;                         // c:448
260pub const COMPCTLMAKEHOOK_OFFSET:     usize = 2;                         // c:449
261pub const COMPCTLCLEANUPHOOK_OFFSET:  usize = 3;                         // c:450
262pub const COMPLISTMATCHESHOOK_OFFSET: usize = 4;                         // c:451
263
264// ---------------------------------------------------------------------------
265// Misc constants.
266// ---------------------------------------------------------------------------
267
268/// Port of `#define CM_SPACE` from `Src/Zle/comp.h:474`. Number of
269/// columns to leave empty between rows of matches.
270pub const CM_SPACE: i32 = 2;                                             // c:474
271
272// ---------------------------------------------------------------------------
273// Typedef structs (c:30-470). C uses linked lists threaded through
274// `next`/`prev` pointers; Rust ports as `Option<Box<T>>` for the
275// owning side.
276// ---------------------------------------------------------------------------
277
278/// Port of `struct cexpl` from `Src/Zle/comp.h:40-45`. Explanation
279/// string entry attached to a match group.
280#[derive(Debug, Clone, Default)]
281#[allow(non_camel_case_types)]
282pub struct Cexpl {                                                       // c:40
283    /// Display even without matches.
284    pub always: i32,                                                     // c:41
285    /// The string itself.
286    pub str: Option<String>,                                            // c:42 (Rust keyword `str`)
287    /// Number of matches.
288    pub count: i32,                                                      // c:43
289    /// Number of matches with fignore ignored.
290    pub fcount: i32,                                                     // c:44
291}
292
293/// Port of `struct cmgroup` from `Src/Zle/comp.h:49-82`. A group of
294/// completion matches (one per `compadd -J GROUP`).
295#[derive(Debug, Clone, Default)]
296#[allow(non_camel_case_types)]
297pub struct Cmgroup {                                                     // c:49
298    /// Group name.
299    pub name: Option<String>,                                            // c:50
300    /// Previous group in the list.
301    pub prev: Option<Box<Cmgroup>>,                                      // c:51
302    /// Next group in the list.
303    pub next: Option<Box<Cmgroup>>,                                      // c:52
304    /// CGF_* flags.
305    pub flags: i32,                                                      // c:53
306    /// Number of matches.
307    pub mcount: i32,                                                     // c:54
308    /// The matches.
309    pub matches: Vec<Cmatch>,                                            // c:55
310    /// Number of things to list here.
311    pub lcount: i32,                                                     // c:56
312    /// Number of line-displays.
313    pub llcount: i32,                                                    // c:57
314    /// Things to list.
315    pub ylist: Vec<String>,                                              // c:58
316    /// Number of explanation strings.
317    pub ecount: i32,                                                     // c:59
318    /// Explanation strings.
319    pub expls: Vec<Cexpl>,                                               // c:60
320    /// Number of compctls used.
321    pub ccount: i32,                                                     // c:61
322    /// LinkList of explanations (mid-build accumulator before `expls`).
323    pub lexpls: Vec<Cexpl>,                                              // c:62
324    /// LinkList of matches (mid-build accumulator before `matches`).
325    pub lmatches: Vec<Cmatch>,                                           // c:63
326    /// LinkList of matches with fignore-removed entries kept.
327    pub lfmatches: Vec<Cmatch>,                                          // c:64
328    /// LinkList of compctls used (mid-build accumulator).
329    pub lallccs: Vec<String>,                                            // c:65
330    /// Group number.
331    pub num: i32,                                                        // c:66
332    /// Number of opened braces.
333    pub nbrbeg: i32,                                                     // c:67
334    /// Number of closed braces.
335    pub nbrend: i32,                                                     // c:68
336    /// New matches since last permalloc().
337    pub new_: i32,                                                       // c:69 (Rust keyword `new`)
338    // c:71-77 — listing accumulators.
339    /// Number of matches to list in columns.
340    pub dcount: i32,                                                     // c:71
341    /// Number of columns.
342    pub cols: i32,                                                       // c:72
343    /// Number of lines.
344    pub lins: i32,                                                       // c:73
345    /// Column width.
346    pub width: i32,                                                      // c:74
347    /// Per-column widths for listpacked.
348    pub widths: Vec<i32>,                                                // c:75
349    /// Total length.
350    pub totl: i32,                                                       // c:76
351    /// Length of shortest match.
352    pub shortest: i32,                                                   // c:77
353    /// Permanent-alloc version of this group (the C source's
354    /// shadow-copy used to survive heap resets).
355    pub perm: Option<Box<Cmgroup>>,                                      // c:78
356}
357
358/// Port of `struct cmatch` from `Src/Zle/comp.h:99-125`. A single
359/// completion match.
360#[derive(Debug, Clone, Default)]
361#[allow(non_camel_case_types)]
362pub struct Cmatch {                                                      // c:99
363    /// The match itself.
364    pub str: Option<String>,                                            // c:100 (Rust keyword)
365    /// The match string unquoted.
366    pub orig: Option<String>,                                            // c:101
367    /// Ignored prefix, has to be re-inserted.
368    pub ipre: Option<String>,                                            // c:102
369    /// Ignored prefix, unquoted.
370    pub ripre: Option<String>,                                           // c:103
371    /// Ignored suffix.
372    pub isuf: Option<String>,                                            // c:104
373    /// The path prefix.
374    pub ppre: Option<String>,                                            // c:105
375    /// The path suffix.
376    pub psuf: Option<String>,                                            // c:106
377    /// Path prefix for opendir.
378    pub prpre: Option<String>,                                           // c:107
379    /// Prefix string from -P.
380    pub pre: Option<String>,                                             // c:108
381    /// Suffix string from -S.
382    pub suf: Option<String>,                                             // c:109
383    /// String to display (compadd -d).
384    pub disp: Option<String>,                                            // c:110
385    /// Closing quote to add automatically.
386    pub autoq: Option<String>,                                           // c:111
387    /// CMF_* flags (cmatch namespace).
388    pub flags: i32,                                                      // c:112
389    /// Places where to put the brace prefixes.
390    pub brpl: Vec<i32>,                                                  // c:113
391    /// ...and the suffixes.
392    pub brsl: Vec<i32>,                                                  // c:114
393    /// When to remove the suffix.
394    pub rems: Option<String>,                                            // c:115
395    /// Shell function to call for suffix-removal.
396    pub remf: Option<String>,                                            // c:116
397    /// Length of quote-prefix.
398    pub qipl: i32,                                                       // c:117
399    /// Length of quote-suffix.
400    pub qisl: i32,                                                       // c:118
401    /// Group-relative number.
402    pub rnum: i32,                                                       // c:119
403    /// Global number.
404    pub gnum: i32,                                                       // c:120
405    /// `mode` field of a stat.
406    pub mode: u32,                                                       // c:121 (mode_t → u32)
407    /// LIST_TYPE-character for mode or 0.
408    pub modec: char,                                                     // c:122
409    /// `mode` field of a stat, following symlink.
410    pub fmode: u32,                                                      // c:123 (mode_t → u32)
411    /// LIST_TYPE-character for fmode or 0.
412    pub fmodec: char,                                                    // c:124
413}
414
415/// Port of `struct cmlist` from `Src/Zle/comp.h:147-151`. Linked
416/// list of global matchers.
417#[derive(Debug, Clone)]
418#[allow(non_camel_case_types)]
419pub struct Cmlist {                                                      // c:147
420    /// Next entry in the list.
421    pub next: Option<Box<Cmlist>>,                                       // c:148
422    /// The matcher definition.
423    pub matcher: Box<Cmatcher>,                                          // c:149
424    /// The string for it.
425    pub str: String,                                                    // c:150
426}
427
428/// Port of `struct cmatcher` from `Src/Zle/comp.h:153-167`. Matcher
429/// specification — what to match on the line vs in the trial word,
430/// with optional left/right anchors.
431#[derive(Debug, Clone, Default)]
432#[allow(non_camel_case_types)]
433pub struct Cmatcher {                                                    // c:153
434    /// Reference counter.
435    pub refc: i32,                                                       // c:154
436    /// Next matcher.
437    pub next: Option<Box<Cmatcher>>,                                     // c:155
438    /// CMF_LINE/CMF_LEFT/CMF_RIGHT/CMF_INTER (cmatcher namespace).
439    pub flags: i32,                                                      // c:156
440    /// What matches on the line.
441    pub line: Option<Box<Cpattern>>,                                     // c:157
442    /// Length of line pattern.
443    pub llen: i32,                                                       // c:158
444    /// What matches in the word.
445    pub word: Option<Box<Cpattern>>,                                     // c:159
446    /// Length of word pattern, or:
447    /// -1: word pattern is one asterisk
448    /// -2: word pattern is two asterisks
449    pub wlen: i32,                                                       // c:160
450    /// Left anchor.
451    pub left: Option<Box<Cpattern>>,                                     // c:163
452    /// Length of left anchor.
453    pub lalen: i32,                                                      // c:164
454    /// Right anchor.
455    pub right: Option<Box<Cpattern>>,                                    // c:165
456    /// Length of right anchor.
457    pub ralen: i32,                                                      // c:166
458}
459
460/// Port of `struct cpattern` from `Src/Zle/comp.h:197-210`. A
461/// single pattern element in a matcher specification — represents
462/// one character either in the trial completion or in the word on
463/// the command line.
464///
465/// The C `union { char *str; convchar_t chr; } u` is dispatched by
466/// `tp` (a `CPAT_*` constant). The Rust port keeps both fields with
467/// `Option`s so the dispatcher reads only the live one.
468#[derive(Debug, Clone, Default)]
469#[allow(non_camel_case_types)]
470pub struct Cpattern {                                                    // c:197
471    /// Next sub-pattern.
472    pub next: Option<Box<Cpattern>>,                                     // c:198
473    /// Type of object — one of CPAT_*.
474    pub tp: i32,                                                         // c:199
475    /// If a character class (CPAT_CCLASS/CPAT_NCLASS/CPAT_EQUIV),
476    /// the objects in it as a metafied string with tokens. Note the
477    /// C allocated length may exceed the null-terminated string.
478    pub str: Option<String>,                                            // c:201 union.u.str
479    /// If a single character (CPAT_CHAR), it.
480    pub chr: u32,                                                        // c:208 union.u.chr (convchar_t)
481}
482
483/// Port of `struct cline` from `Src/Zle/comp.h:245-257`. One
484/// word-part in the unambiguous-line-string list. Threaded prefix /
485/// suffix sub-lists via the `prefix`/`suffix` fields.
486#[derive(Debug, Clone, Default)]
487#[allow(non_camel_case_types)]
488pub struct Cline {                                                       // c:245
489    /// Next sibling word-part.
490    pub next: Option<Box<Cline>>,                                        // c:246
491    /// CLF_* flags.
492    pub flags: i32,                                                      // c:247
493    /// Line string for this part.
494    pub line: Option<String>,                                            // c:248
495    /// Length of `line`.
496    pub llen: i32,                                                       // c:249
497    /// Word string for this part.
498    pub word: Option<String>,                                            // c:250
499    /// Length of `word`.
500    pub wlen: i32,                                                       // c:251
501    /// Original (unjoined) string.
502    pub orig: Option<String>,                                            // c:252
503    /// Length of `orig`.
504    pub olen: i32,                                                       // c:253
505    /// String length (the join-up version).
506    pub slen: i32,                                                       // c:254
507    /// Prefix sub-list.
508    pub prefix: Option<Box<Cline>>,                                      // c:255
509    /// Suffix sub-list.
510    pub suffix: Option<Box<Cline>>,                                      // c:255
511    /// Min length seen for this part (joining metric).
512    pub min: i32,                                                        // c:256
513    /// Max length seen for this part (joining metric).
514    pub max: i32,                                                        // c:256
515}
516
517/// Port of `struct aminfo` from `Src/Zle/comp.h:274-280`. Holds
518/// info about ambiguous completions — there's one for fignore-
519/// ignored and one for normal completion.
520#[derive(Debug, Clone, Default)]
521#[allow(non_camel_case_types)]
522pub struct Aminfo {                                                      // c:274
523    /// The first match.
524    pub firstm: Option<Box<Cmatch>>,                                     // c:275
525    /// If there was an exact match.
526    pub exact: i32,                                                      // c:276
527    /// The exact match (if any).
528    pub exactm: Option<Box<Cmatch>>,                                     // c:277
529    /// Number of matches.
530    pub count: i32,                                                      // c:278
531    /// Unambiguous line string.
532    pub line: Option<Box<Cline>>,                                        // c:279
533}
534
535/// Port of `struct menuinfo` from `Src/Zle/comp.h:284-295`.
536/// Menu-completion state.
537#[derive(Debug, Clone, Default)]
538#[allow(non_camel_case_types)]
539pub struct Menuinfo {                                                    // c:284
540    /// Position in the group list.
541    pub group: Option<Box<Cmgroup>>,                                     // c:285
542    /// Match currently inserted.
543    pub cur: Option<Box<Cmatch>>,                                        // c:286
544    /// Begin on line.
545    pub pos: i32,                                                        // c:287
546    /// Length of inserted string.
547    pub len: i32,                                                        // c:288
548    /// End on the line.
549    pub end: i32,                                                        // c:289
550    /// Non-zero if the cursor was at the end.
551    pub we: i32,                                                         // c:290
552    /// Length of suffix inserted.
553    pub insc: i32,                                                       // c:291
554    /// We asked if the list should be shown.
555    pub asked: i32,                                                      // c:292
556    /// Prefix before a brace, if any.
557    pub prebr: Option<String>,                                           // c:293
558    /// Suffix after a brace.
559    pub postbr: Option<String>,                                          // c:294
560}
561
562/// Port of `struct ccmakedat` from `Src/Zle/comp.h:455-459`. Hook
563/// data passed to the compctl-make path.
564#[derive(Debug, Clone, Default)]
565#[allow(non_camel_case_types)]
566pub struct Ccmakedat {                                                   // c:455
567    /// String passed to the hook.
568    pub str: Option<String>,                                            // c:456
569    /// Whether we're in a command position.
570    pub incmd: i32,                                                      // c:457
571    /// List flag.
572    pub lst: i32,                                                        // c:458
573}
574
575/// Port of `struct chdata` from `Src/Zle/comp.h:465-470`. Data
576/// given to `offered` hooks.
577#[derive(Debug, Clone, Default)]
578#[allow(non_camel_case_types)]
579pub struct Chdata {                                                      // c:465
580    /// The matches generated.
581    pub matches: Option<Box<Cmgroup>>,                                   // c:466
582    /// Number of matches.
583    pub num: i32,                                                        // c:467
584    /// Number of messages.
585    pub nmesg: i32,                                                      // c:468
586    /// Current match or None.
587    pub cur: Option<Box<Cmatch>>,                                        // c:469
588}
589
590/// Port of `struct cadata` from `Src/Zle/comp.h:315-337`. Data
591/// passed to compadd / addmatches().
592#[derive(Debug, Clone, Default)]
593#[allow(non_camel_case_types)]
594pub struct Cadata {                                                      // c:315
595    /// Ignored prefix (-i).
596    pub ipre: Option<String>,                                            // c:316
597    /// Ignored suffix (-I).
598    pub isuf: Option<String>,                                            // c:317
599    /// `path` prefix (-p).
600    pub ppre: Option<String>,                                            // c:318
601    /// `path` suffix (-s).
602    pub psuf: Option<String>,                                            // c:319
603    /// Expanded `path` prefix (-W).
604    pub prpre: Option<String>,                                           // c:320
605    /// Prefix to insert (-P).
606    pub pre: Option<String>,                                             // c:321
607    /// Suffix to insert (-S).
608    pub suf: Option<String>,                                             // c:322
609    /// Name of the group (`-[JV]`).
610    pub group: Option<String>,                                           // c:323
611    /// Remove suffix on chars... (-r).
612    pub rems: Option<String>,                                            // c:324
613    /// Function to remove suffix (-R).
614    pub remf: Option<String>,                                            // c:325
615    /// Ignored suffixes (-F).
616    pub ign: Option<String>,                                             // c:326
617    /// CMF_* flags (`-[fqn]`).
618    pub flags: i32,                                                      // c:327
619    /// CAF_* flags (`-[QUa]`).
620    pub aflags: i32,                                                     // c:328
621    /// Match spec (parsed from -M).
622    pub match_: Option<Box<Cmatcher>>,                                   // c:329 (Rust keyword)
623    /// Explanation (-X).
624    pub exp: Option<String>,                                             // c:330
625    /// Array to store matches in (-A).
626    pub apar: Option<String>,                                            // c:331
627    /// Array to store originals in (-O).
628    pub opar: Option<String>,                                            // c:332
629    /// Arrays to delete non-matches in (-D).
630    pub dpar: Vec<String>,                                               // c:333
631    /// Array with display lists (-d).
632    pub disp: Option<String>,                                            // c:334
633    /// Message to show unconditionally (-x).
634    pub mesg: Option<String>,                                            // c:335
635    /// Add that many dummy matches.
636    pub dummies: i32,                                                    // c:336
637}
638
639/// Port of `struct cldata` from `Src/Zle/comp.h:343-353`. List data
640/// for the matches-listing path.
641#[derive(Debug, Clone, Default)]
642#[allow(non_camel_case_types)]
643pub struct Cldata {                                                      // c:343
644    /// Screen width.
645    pub zterm_columns: i32,                                              // c:344
646    /// Screen height.
647    pub zterm_lines: i32,                                                // c:345
648    /// Value of global menuacc.
649    pub menuacc: i32,                                                    // c:346
650    /// No need to calculate anew.
651    pub valid: i32,                                                      // c:347
652    /// Number of matches to list.
653    pub nlist: i32,                                                      // c:348
654    /// Number of lines needed.
655    pub nlines: i32,                                                     // c:349
656    /// != 0 if there are hidden matches.
657    pub hidden: i32,                                                     // c:350
658    /// != 0 if only explanations to print.
659    pub onlyexpl: i32,                                                   // c:351
660    /// != 0 if hidden matches should be shown.
661    pub showall: i32,                                                    // c:352
662}
663
664#[cfg(test)]
665mod tests {
666    use super::*;
667
668    /// Verifies CGF_* group flag values per c:85-95.
669    #[test]
670    fn cgf_flags_correct() {
671        let _g = crate::ported::zle::zle_main::zle_test_setup();
672        assert_eq!(CGF_NOSORT, 1);
673        assert_eq!(CGF_LINES, 2);
674        assert_eq!(CGF_HASDL, 4);
675        assert_eq!(CGF_REVSORT, 1024);
676    }
677
678    /// Verifies CMF_* match flags are non-overlapping single-bits
679    /// per c:127-143.
680    #[test]
681    fn cmf_match_flags_distinct() {
682        let _g = crate::ported::zle::zle_main::zle_test_setup();
683        let all = CMF_FILE | CMF_REMOVE | CMF_ISPAR | CMF_PARBR
684                | CMF_PARNEST | CMF_NOLIST | CMF_DISPLINE | CMF_HIDE
685                | CMF_NOSPACE | CMF_PACKED | CMF_ROWS | CMF_MULT
686                | CMF_FMULT | CMF_ALL | CMF_DUMMY | CMF_MORDER
687                | CMF_DELETE;
688        assert_eq!(all.count_ones(), 17);
689    }
690
691    /// Verifies CMF_LINE/LEFT/RIGHT/INTER cmatcher flags per c:172-178.
692    #[test]
693    fn cmf_matcher_flags_correct() {
694        let _g = crate::ported::zle::zle_main::zle_test_setup();
695        assert_eq!(CMF_LINE, 1);
696        assert_eq!(CMF_LEFT, 2);
697        assert_eq!(CMF_RIGHT, 4);
698        assert_eq!(CMF_INTER, 8);
699    }
700
701    /// Verifies CPAT_* enum values per c:184-190.
702    #[test]
703    fn cpat_enum_values_correct() {
704        let _g = crate::ported::zle::zle_main::zle_test_setup();
705        assert_eq!(CPAT_CCLASS, 0);
706        assert_eq!(CPAT_NCLASS, 1);
707        assert_eq!(CPAT_EQUIV, 2);
708        assert_eq!(CPAT_ANY, 3);
709        assert_eq!(CPAT_CHAR, 4);
710    }
711
712    /// Verifies CP_REALPARAMS / CP_ALLREALS aggregate per c:385-386.
713    #[test]
714    fn cp_realparams_mask_covers_10_bits() {
715        let _g = crate::ported::zle::zle_main::zle_test_setup();
716        assert_eq!(CP_REALPARAMS, 10);
717        assert_eq!(CP_ALLREALS, 0x3ff);
718        assert_eq!(CP_ALLREALS.count_ones(), 10);
719        assert_eq!(CP_WORDS | CP_REDIRS | CP_CURRENT | CP_PREFIX
720                  | CP_SUFFIX | CP_IPREFIX | CP_ISUFFIX
721                  | CP_QIPREFIX | CP_QISUFFIX | CP_COMPSTATE,
722                  CP_ALLREALS);
723    }
724
725    /// Verifies CP_KEYPARAMS / CP_ALLKEYS aggregate per c:442-443.
726    #[test]
727    fn cp_keyparams_mask_covers_26_bits() {
728        let _g = crate::ported::zle::zle_main::zle_test_setup();
729        assert_eq!(CP_KEYPARAMS, 26);
730        assert_eq!(CP_ALLKEYS, 0x3ffffff);
731        assert_eq!(CP_ALLKEYS.count_ones(), 26);
732    }
733
734    /// Verifies CAF_* compadd flags per c:299-309.
735    #[test]
736    fn caf_flags_correct() {
737        let _g = crate::ported::zle::zle_main::zle_test_setup();
738        assert_eq!(CAF_QUOTE, 1);
739        assert_eq!(CAF_NOSORT, 2);
740        assert_eq!(CAF_REVSORT, 1024);
741    }
742
743    /// Verifies hook offset constants per c:447-451.
744    #[test]
745    fn hook_offsets_sequential() {
746        let _g = crate::ported::zle::zle_main::zle_test_setup();
747        assert_eq!(INSERTMATCHHOOK_OFFSET, 0);
748        assert_eq!(MENUSTARTHOOK_OFFSET, 1);
749        assert_eq!(COMPCTLMAKEHOOK_OFFSET, 2);
750        assert_eq!(COMPCTLCLEANUPHOOK_OFFSET, 3);
751        assert_eq!(COMPLISTMATCHESHOOK_OFFSET, 4);
752    }
753
754    /// Verifies CM_SPACE per c:474.
755    #[test]
756    fn cm_space_is_2() {
757        let _g = crate::ported::zle::zle_main::zle_test_setup();
758        assert_eq!(CM_SPACE, 2);
759    }
760
761    /// Verifies the structs construct cleanly with `Default`.
762    #[test]
763    fn structs_default_construct() {
764        let _g = crate::ported::zle::zle_main::zle_test_setup();
765        let _ = Cexpl::default();
766        let _ = Cmgroup::default();
767        let _ = Cmatch::default();
768        let _ = Cmatcher::default();
769        let _ = Cpattern::default();
770        let _ = Cline::default();
771        let _ = Aminfo::default();
772        let _ = Menuinfo::default();
773        let _ = Ccmakedat::default();
774        let _ = Chdata::default();
775        let _ = Cadata::default();
776        let _ = Cldata::default();
777    }
778}