xref: /freebsd/stand/lua/menu.lua.8 (revision 76238846ad3e9e271a3d1f792f72beab727fd153)
1.\"
2.\" SPDX-License-Identifier: BSD-2-Clause
3.\"
4.\" Copyright (c) 2018 Kyle Evans <kevans@FreeBSD.org>
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\"
15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25.\" SUCH DAMAGE.
26.\"
27.\" $FreeBSD$
28.\"
29.Dd March 31, 2021
30.Dt MENU.LUA 8
31.Os
32.Sh NAME
33.Nm menu.lua
34.Nd FreeBSD dynamic menu boot module
35.Sh DESCRIPTION
36.Nm
37contains the main functionality required to build a dynamic menu system.
38It also contains definitions for the built-in menus, some of which are
39influenced by
40.Xr loader 8
41environment variables.
42.Pp
43Before hooking into the functionality provided by
44.Nm ,
45it must be included with a statement such as the following:
46.Pp
47.Dl local menu = require("menu")
48.Ss MENU DEFINITIONS
49Menus are represented in
50.Nm
51as a table.
52That table
53.Sy must
54contain an
55.Va entries
56key.
57.Pp
58If the value of the
59.Va entries
60key is itself a table, then each value in this table defines a single entry in
61this menu.
62See
63.Sx MENU ITEM DEFINITIONS
64for the structure of each entry.
65.Pp
66.Va entries
67may also be a function.
68This function must return a table, each value of which defines a single entry
69in this menu.
70See
71.Sx MENU ITEM DEFINITIONS .
72.Ss MENU ITEM DEFINITIONS
73The following keys may be defined for a menu item:
74.Bl -tag -width disable-module_module -offset indent
75.It Ic entry_type
76The type of this menu entry.
77See
78.Sx MENU ITEM TYPES .
79.It Ic carousel_id
80A unique string id for this carousel.
81A carousel is a menu entry that rotates through a selection of items.
82Used for storage of the carousel's current setting.
83.It Ic visible
84A lambda that returns
85.Dv true
86if this menu item should be visible and
87.Dv false
88if it should not be visible.
89.It Ic items
90A table (or a lambda that returns a table) of the possible choices for this
91carousel.
92.It Ic name
93A string (or a lambda that returns a string) containing the current name of this
94item.
95.It Ic func
96The function executed when this entry is selected.
97Every type except for
98.Ic core.MENU_SEPARATOR
99may have a
100.Ic func .
101.It Ic submenu
102The submenu menu definition to draw when this entry is selected.
103.It Ic alias
104A table of case-sensitive aliases for this menu entry.
105All menu entries that can be selected may have any number of
106.Ic alias
107entries.
108.El
109.Pp
110.Ic entry_type
111is the only required key for every entry type.
112.Ic name
113is required for all entry types except for
114.Ic core.MENU_SEPARATOR .
115.Ss MENU ITEM TYPES
116The menu item type constants are defined in
117.Xr core.lua 8 .
118The following types are available:
119.Bl -tag -width core.MENU_CAROUSEL_ENTRY -offset indent
120.It Ic core.MENU_RETURN
121Return to the parent menu.
122If the current menu is the default menu,
123.Nm
124will exit the menu and begin the autoboot sequence (if applicable).
125This type of menu entry may execute
126.Ic func ,
127when selected, and has a
128.Ic name .
129.It Ic core.MENU_ENTRY
130A normal menu entry that executes
131.Ic func
132when selected, and has a
133.Ic name .
134.It Ic core.MENU_SEPARATOR
135A menu entry that serves as a separator.
136It may have a
137.Ic name .
138.It Ic core.MENU_SUBMENU
139A menu entry that opens
140.Ic submenu
141when selected.
142It may have a
143.Ic name .
144.It Ic core.MENU_CAROUSEL_ENTRY
145A menu entry that rotates through
146.Ic items
147like a carousel.
148.Ic func
149is executed when selected, and the callback is passed the choice index, name of
150the current choice, and the table of choices.
151.El
152.Ss EXPORTED MENUS
153The following menus are exported by
154.Nm :
155.Bl -tag -width menu.boot_environments -offset indent
156.It Ic menu.default
157The default menu to draw.
158Set to
159.Ic menu.welcome
160by default.
161.It Ic menu.welcome
162The welcome menu.
163Contains single and multi user boot options, as well as entries to access other
164menus.
165.It Ic menu.boot_options
166The "Boot Options" menu.
167.It Ic menu.boot_environments
168The "Boot Environments" menu.
169This menu is only visible if the system is booted on a ZFS partition and more
170than one boot environment was detected at boot.
171.El
172.Sh EXAMPLES
173To replace the default boot menu with a simple boot menu:
174.Pp
175.Bd -literal -offset indent -compact
176local core = require("core")
177local menu = require("menu")
178
179menu.default = {
180	entries = {
181		{
182			entry_type = core.MENU_ENTRY,
183			name = "Boot",
184			func = core.boot,
185		},
186		{
187			entry_type = core.MENU_CAROUSEL_ENTRY,
188			carousel_id = "unique_boot_entry_name",
189			items = {"NO", "YES"},
190			name = function(_, choice, _)
191				return "Option: " .. choice
192			end,
193			func = function(_, _, _)
194				loader.setenv("some_envvar", "some_value")
195			end,
196		},
197	},
198}
199.Ed
200.Pp
201To add another option to the welcome menu:
202.Pp
203.Bd -literal -offset indent -compact
204local core = require("core")
205local menu = require("menu")
206
207local my_entry = {
208	entry_type = core.MENU_ENTRY,
209	name = "Fancy Boot",
210	func = core.boot,
211},
212
213local stock_entries = menu.welcome.entries
214function menu.welcome.entries()
215	local ents = stock_entries()
216	ents[#ents + 1] = my_entry
217	return ents
218end
219.Ed
220.Pp
221To create a vendor submenu or other vendor menu option,
222override
223.Ic menu.welcome.all_entires.vendor
224like so:
225.Pp
226.Bd -literal -offset indent -compact
227local core = require("core")
228local menu = require("menu")
229
230-- Fill in with vendor specific entries
231local vendor_options = {
232	entries = {
233	...
234	},
235}
236
237local welcome_entries = menu.welcome.all_entries
238welcome_entries.vendor = {
239        entry_type = core.MENU_SUBMENU,
240        name = color.highlight("V") .. "endor Options",
241        submenu = vendor_options,
242        alias = {"v", "V"},
243	visible = function()
244		return true
245	end,
246}
247.Ed
248In the above example,
249.Ic vendor_options
250is a local variable that defines the vendor submenu.
251.Pp
252To add an additional option, change the
253.Ic menu.boot_options.entries
254array.
255The following illustrates this concept:
256.Pp
257.Bd -literal -offset indent -compact
258-- This is a silly example that rotates local_option through the values
259-- 0 to 4.  local_option would still need to be used elsewhere.
260local local_option = 0
261
262-- The `entries` of a menu may either be a table or a function.  In this
263-- example we're augmenting a menu that just has a static table, but if we
264-- wanted to be more robust then we would need to instead check the type
265-- of `stock_options` here to determine our next move.
266--
267-- If `entries` is a table, then the stock menu system won't be changing it
268-- so we can just add our menu option as we do below.
269--
270-- If `entries` is a function, then we would need to provide a new function to
271-- replace `entries` that does a core.deepCopyTable() of the result and adds
272-- the below item to it.  The deep copy is necessary to avoid duplicating our
273-- new menu item and allowing the menu to alter its behavior however it pleases.
274local stock_options = menu.boot_options.entries
275stock_options[#stock_options + 1] = {
276	entry_type = core.MENU_ENTRY,
277	name = function()
278		return color.highlight('L') ..
279		    "ocal Option     : " .. local_option
280	end,
281	func = function()
282		local_option = (local_option + 1) % 5
283	end,
284	alias= {"l", "L"}
285}
286.Sh SEE ALSO
287.Xr loader.conf 5 ,
288.Xr core.lua 8 ,
289.Xr loader 8
290.Sh HISTORY
291The
292.Nm
293file first appeared in
294.Fx 12.0 .
295.Sh AUTHORS
296The
297.Nm
298file was originally written by
299.An Pedro Souza Aq Mt pedrosouza@FreeBSD.org .
300Later work and this manual page was done by
301.An Kyle Evans Aq Mt kevans@FreeBSD.org .
302