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