Matrix protocol in OCaml, Eio specialised
1(** Cmdliner terms for Matrix CLI applications.
2
3 This module provides reusable cmdliner terms and combinators for building
4 Matrix client command-line interfaces. It follows the principle of
5 separation: parsing logic lives here, whilst business logic should remain
6 in plain OCaml functions that receive already-parsed values.
7
8 {2 Design Principles}
9
10 - {b Clarity}: Each option has a single, clearly stated purpose
11 - {b Orthogonality}: Each flag controls one independent aspect
12 - {b Discoverability}: Good --help output with defaults documented
13 - {b Composability}: Terms can be combined for different CLI tools
14
15 {2 Example Usage}
16
17 {[
18 open Cmdliner
19
20 let run ~homeserver ~profile ~verbose () =
21 (* your implementation *)
22 ()
23
24 let term =
25 let open Matrix_client.Cmd in
26 Term.(const run
27 $ homeserver_term
28 $ profile_term
29 $ verbose_term)
30
31 let cmd =
32 let info = Cmd.info "myapp" ~doc:"My Matrix app" in
33 Cmd.v info term
34 ]} *)
35
36open Cmdliner
37
38(** {1 Connection Options} *)
39
40(** Matrix homeserver URL term.
41
42 Accepts [--homeserver URL] or [-s URL], with fallback to
43 [MATRIX_HOMESERVER] environment variable.
44
45 @return The homeserver URL as a string *)
46val homeserver_term : string Term.t
47
48(** Matrix homeserver URL term (optional).
49
50 Like {!homeserver_term} but returns [None] if not specified.
51 Useful when a stored session may provide the homeserver. *)
52val homeserver_opt_term : string option Term.t
53
54(** {1 Authentication Options} *)
55
56(** Username term.
57
58 Accepts [--username USER] or [-u USER], with fallback to
59 [MATRIX_USERNAME] environment variable. Accepts either a
60 localpart or full [@user:server] format. *)
61val username_term : string Term.t
62
63(** Username term (optional). *)
64val username_opt_term : string option Term.t
65
66(** Password term.
67
68 Accepts [--password PASS] or [-p PASS], with fallback to
69 [MATRIX_PASSWORD] environment variable.
70
71 {b Security note}: The environment variable is preferred
72 over the command-line flag to avoid password exposure in
73 process listings. *)
74val password_term : string Term.t
75
76(** Password term (optional). *)
77val password_opt_term : string option Term.t
78
79(** {1 Session Management} *)
80
81(** Profile name term.
82
83 Accepts [--profile NAME] with default ["default"].
84 Profiles are stored in [$XDG_DATA_HOME/matrix/profiles/NAME/].
85
86 Multiple profiles allow managing several Matrix accounts
87 on the same machine. *)
88val profile_term : string Term.t
89
90(** {1 Target Options} *)
91
92(** Room ID term.
93
94 Accepts [--room ROOM_ID] or [-r ROOM_ID].
95 The room ID should be in the format [!roomid:server]. *)
96val room_term : string Term.t
97
98(** Room ID term (optional). *)
99val room_opt_term : string option Term.t
100
101(** Recipient user ID term.
102
103 Accepts [--to USER_ID] or [-t USER_ID].
104 The user ID should be in the format [@user:server].
105 Used for direct messages. *)
106val recipient_term : string Term.t
107
108(** Recipient user ID term (optional). *)
109val recipient_opt_term : string option Term.t
110
111(** {1 Message Options} *)
112
113(** Message body term.
114
115 A positional argument for the message text to send. *)
116val message_term : string Term.t
117
118(** Message body term (optional). *)
119val message_opt_term : string option Term.t
120
121(** {1 Encryption Options} *)
122
123(** Encrypted flag term.
124
125 Accepts [--encrypted] or [-e].
126 Enables end-to-end encryption for newly created rooms. *)
127val encrypted_term : bool Term.t
128
129(** {1 Logging Options} *)
130
131(** Verbosity level term.
132
133 Accepts [-v] (repeatable) for increasing verbosity:
134 - No flags: warnings and errors only
135 - [-v]: info messages
136 - [-v -v]: debug messages
137
138 Also respects [--color] for output styling.
139
140 This term returns [unit] and sets up logging as a side effect
141 when the term is evaluated. *)
142val verbosity_term : unit Term.t
143
144(** {1 Argument Converters} *)
145
146(** Cmdliner converter for Matrix user IDs.
147
148 Validates that the string is a valid user ID in the format
149 [@localpart:server]. *)
150val user_id_conv : Matrix_proto.Id.User_id.t Arg.conv
151
152(** Cmdliner converter for Matrix room IDs.
153
154 Validates that the string is a valid room ID in the format
155 [!opaque_id:server]. *)
156val room_id_conv : Matrix_proto.Id.Room_id.t Arg.conv
157
158(** Cmdliner converter for URIs. *)
159val uri_conv : Uri.t Arg.conv
160
161(** {1 Parsed Types}
162
163 Record types for collecting parsed arguments, useful for
164 structuring command implementations. *)
165
166(** Credentials for password-based login. *)
167type login_credentials = {
168 homeserver : string;
169 username : string;
170 password : string;
171 profile : string;
172}
173
174(** Term that collects login credentials. *)
175val login_credentials_term : login_credentials Term.t
176
177(** Target for sending a message (room or DM). *)
178type message_target =
179 | Room of string (** Room ID *)
180 | Direct of string (** Recipient user ID *)
181
182(** Message parameters for sending. *)
183type message_params = {
184 target : message_target;
185 body : string;
186 encrypted : bool;
187}
188
189(** {1 Command Builders}
190
191 Helper functions for building common command patterns. *)
192
193(** Exit codes following standard conventions.
194
195 - [exit_ok]: Success (0)
196 - [exit_usage]: Usage error (64)
197 - [exit_auth]: Authentication failure (77)
198 - [exit_network]: Network error (69)
199 - [exit_internal]: Internal error (70) *)
200
201val exit_ok : Cmd.Exit.code
202val exit_usage : Cmd.Exit.code
203val exit_auth : Cmd.Exit.code
204val exit_network : Cmd.Exit.code
205val exit_internal : Cmd.Exit.code