1.\" 2.\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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