# Layouts #### Example: Defining Custom Layout [![layout.png][23]][24] ```lua xplr.config.layouts.builtin.default = { Horizontal = { config = { margin = 1, horizontal_margin = 2, vertical_margin = 3, constraints = { { Percentage = 50 }, { Percentage = 50 }, } }, splits = { "Table", "HelpMenu", } } } ``` xplr layouts define the structure of the UI, i.e. how many panel we see, placement and size of the panels, how they look etc. This is configuration exposed via the `xplr.config.layouts` API. It contains the following fields: - [builtin][1] - [custom][2] The users can switch between these layouts at run-time. ## builtin Type: mapping of string and [Layout][3] This is exposed by the `xplr.config.layouts.builtin` API. xplr by default provides the following builtin layouts: - [default][4] - [no_help][5] - [no_selection][6] - [no_help_no_selection][7] ### default Type: [Layout][3] This is the default layout we see when we run xplr. ### no_help Type: [Layout][3] This layout hides the help menu. ### no_selection Type: [Layout][3] This layout hides the selection panel. ### no_help_no_selection Type: [Layout][3] This layout hides both the help menu and the selection panel. ## custom Type: mapping of string and [Layout][3] This is exposed by the `xplr.config.layouts.custom` API. It allows the users to define any custom layout. Example: ```lua xplr.config.layouts.custom.example = "Nothing" xplr.config.general.initial_layout = "example" -- when you load xplr, you should see a blank screen ``` ## Layout A layout can be one of the following: - ["Nothing"][8] - ["Table"][9] - ["InputAndLogs"][10] - ["Selection"][11] - ["HelpMenu"][12] - ["SortAndFilter"][13] - { [CustomContent][25] = { [title][33], [body][34] } - { [Horizontal][14] = { [config][15], [splits][17] } - { [Vertical][16] = { [config][15], [splits][17] } ### Nothing This layout contains a blank panel. ### Table This layout contains the table displaying the files and directories in the current directory. ### InputAndLogs This layout contains the panel displaying the input prompt and logs. ### Selection This layout contains the panel displaying the selected paths. ### HelpMenu This layout contains the panel displaying the help menu for the current mode in real-time. ### SortAndFilter This layout contains the panel displaying the pipeline of sorters and filters applied of the list of paths being displayed. ### Horizontal This is a special layout that splits the panel into two horizontal parts. It contains the following information: - [config][15] - [splits][17] ### Vertical This is a special layout that splits the panel into two vertical parts. It contains the following information: - [config][15] - [splits][17] ## Layout Config A layout config contains the following information: - [margin][18] - [horizontal_margin][19] - [vertical_margin][20] - [constraints][21] ### margin Type: nullable integer The width of the margin in all direction. ### horizontal_Margin Type: nullable integer The width of the horizontal margins. Overwrites the [margin][18] value. ### vertical_Margin Type: nullable integer The width of the vertical margins. Overwrites the [margin][18] value. ### constraints Type: nullable list of [Constraint][22] The constraints applied on the layout. ## Constraint A constraint can be one of the following: - { Percentage = int } - { Ratio = { int, int } } - { Length = { int } - { LengthLessThanScreenHeight = int } - { LengthLessThanScreenWidth = int } - { LengthLessThanLayoutHeight = int } - { LengthLessThanLayoutWidth = int } - { Max = int } - { MaxLessThanScreenHeight = int } - { MaxLessThanScreenWidth = int } - { MaxLessThanLayoutHeight = int } - { MaxLessThanLayoutWidth = int } - { Min = int } - { MinLessThanScreenHeight = int } - { MinLessThanScreenWidth = int } - { MinLessThanLayoutHeight = int } - { MinLessThanLayoutWidth = int } TODO: document each constraint. ## splits Type: list of [Layout][3] The list of child layouts to fit into the parent layout. ## Custom Content Custom content is a special layout to render something custom. It contains the following information: - [title][33] - [body][34] ### title Type: nullable string The title of the panel. ### body Type: [Content Body][26] The body of the panel. ## Content Body Content body can be one of the following: - [StaticParagraph][27] - [DynamicParagraph][28] - [StaticList][29] - [DynamicList][30] - [StaticTable][31] - [DynamicTable][32] ### Static Paragraph A paragraph to render. It contains the following fields: - **render** (string): The string to render. #### Example: Render a custom static paragraph ```lua xplr.config.layouts.builtin.default = { CustomContent = { title = "custom title", body = { StaticParagraph = { render = "custom body" }, }, }, } ``` ### Dynamic Paragraph A [Lua function][35] to render a custom paragraph. It contains the following fields: - **render** (string): The [lua function][35] that returns the paragraph to render. #### Example: Render a custom dynamic paragraph ```lua xplr.config.layouts.builtin.default = { CustomContent = { title = "custom title", body = { DynamicParagraph = { render = "custom.render_layout" } }, }, } xplr.fn.custom.render_layout = function(ctx) return ctx.app.pwd end ``` ### Static List A list to render. It contains the following fields: - **render** (list of string): The list to render. #### Example: Render a custom static list ```lua xplr.config.layouts.builtin.default = { CustomContent = { title = "custom title", body = { StaticList = { render = { "1", "2", "3" } }, }, }, } ``` ### Dynamic List A [Lua function][35] to render a custom list. It contains the following fields: - **render** (string): The [lua function][35] that returns the list to render. #### Example: Render a custom dynamic list ```lua xplr.config.layouts.builtin.default = { CustomContent = { title = "custom title", body = { DynamicList = { render = "custom.render_layout" } }, }, } xplr.fn.custom.render_layout = function(ctx) return { ctx.app.pwd, ctx.app.version, tostring(ctx.app.pid), } end ``` ### Static Table A table to render. It contains the following fields: - **widths** (list of [Constraint][22]): Width of the columns. - **col_spacing** (nullable int): Spacing between columns. Defaults to 1. - **render** (list of list of string): The rows and columns to render. #### Example: Render a custom static table ```lua xplr.config.layouts.builtin.default = { CustomContent = { title = "custom title", body = { StaticTable = { widths = { { Percentage = 50 }, { Percentage = 50 }, }, col_spacing = 1, render = { { "a", "b" }, { "c", "d" }, }, }, }, }, } ``` ### Dynamic Table A [Lua function][35] to render a custom table. It contains the following fields: - **widths** (list of [Constraint][22]): Width of the columns. - **col_spacing** (nullable int): Spacing between columns. Defaults to 1. - **render** (string): The [lua function][35] that returns the table to render. #### Example: Render a custom dynamic table ```lua xplr.config.layouts.builtin.default = { CustomContent = { title = "custom title", body = { DynamicTable = { widths = { { Percentage = 50 }, { Percentage = 50 }, }, col_spacing = 1, render = "custom.render_layout", }, }, }, } xplr.fn.custom.render_layout = function(ctx) return { { "", "" }, { "Layout height", tostring(ctx.layout_size.height) }, { "Layout width", tostring(ctx.layout_size.width) }, { "", "" }, { "Screen height", tostring(ctx.screen_size.height) }, { "Screen width", tostring(ctx.screen_size.width) }, } end ``` ## Content Renderer It is a Lua function that receives [a special argument][36] as input and returns some output that can be rendered in the UI. It is used to render content body for the custom dynamic layouts. ## Content Renderer Argument It contains the following information: - [layout_size][37] - [screen_size][37] - [app][38] ### Size It contains the following information: - x - y - height - width Every field is of integer type. ### app This is a lightweight version of the [Lua Context][39]. In this context, the heavyweight fields like [directory_buffer][50] are omitted for performance reasons. Hence, only the following fields are avilable. - [version][40] - [pwd][41] - [focused_node][42] - [selection][43] - [mode][44] - [layout][45] - [input_buffer][46] - [pid][47] - [session_path][48] - [explorer_config][49] [1]: #builtin [2]: #custom [3]: #layout [4]: #default [5]: #no_help [6]: #no_selection [7]: #no_help_no_selection [8]: #nothing [9]: #table [10]: #inputandlogs [11]: #selection [12]: #helpmenu [13]: #sortandfilter [14]: #horizontal [15]: #layout-config [16]: #vertical [17]: #splits [18]: #margin [19]: #horizontal_margin [20]: #vertical_margin [21]: #constraints [22]: #constraint [23]: https://s6.gifyu.com/images/layout.png [24]: https://gifyu.com/image/1X38 [25]: #custom-content [26]: #content-body [27]: #static-paragraph [28]: #dynamic-paragraph [29]: #static-list [30]: #dynamic-list [31]: #static-table [32]: #dynamic-table [33]: #title [34]: #body [35]: #content-renderer [36]: #content-renderer-argument [37]: #size [38]: #app [39]: message.md#lua-context [40]: message.md#version [41]: message.md#pwd [42]: message.md#focused_node [43]: message.md#selection [44]: message.md#mode [45]: message.md#layout [46]: message.md#input_buffer [47]: message.md#pid [48]: message.md#session_path [49]: message.md#explorer_config [50]: message.md#directory_buffer