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.Ed 285.Sh SEE ALSO 286.Xr loader.conf 5 , 287.Xr core.lua 8 , 288.Xr loader 8 289.Sh HISTORY 290The 291.Nm 292file first appeared in 293.Fx 12.0 . 294.Sh AUTHORS 295The 296.Nm 297file was originally written by 298.An Pedro Souza Aq Mt pedrosouza@FreeBSD.org . 299Later work and this manual page was done by 300.An Kyle Evans Aq Mt kevans@FreeBSD.org . 301