mirror of
https://github.com/kristoferssolo/solorice.git
synced 2025-10-21 20:10:34 +00:00
1039 lines
30 KiB
Lua
1039 lines
30 KiB
Lua
--- @diagnostic disable: undefined-global, undefined-field
|
|
--- @alias Mode Mode Comes from Yazi.
|
|
--- @alias Rect Rect Comes from Yazi.
|
|
--- @alias Paragraph Paragraph Comes from Yazi.
|
|
--- @alias Line Line Comes from Yazi.
|
|
--- @alias Span Span Comes from Yazi.
|
|
--- @alias Color Color Comes from Yazi.
|
|
--- @alias Config Config The config used for setup.
|
|
--- @alias Coloreds Coloreds The array returned by colorizer in {{string, Color}, {string, Color} ... } format
|
|
--- @alias Side # [ LEFT ... RIGHT ]
|
|
--- | `enums.LEFT` # The left side of either the header-line or status-line. [ LEFT ... ]
|
|
--- | `enums.RIGHT` # The right side of either the header-line or status-line. [ ... RIGHT]
|
|
--- @alias SeparatorType
|
|
--- | `enums.OUTER` # Separators on the outer side of sections. [ c o | c o | c o ... ] or [ ... o c | o c | o c ]
|
|
--- | `enums.INNER` # Separators on the inner side of sections. [ c i c | c i c | c i c ... ] or [ ... c i c | c i c | c i c ]
|
|
--- @alias ComponentType
|
|
--- | `enums.A` # Components on the first section. [ A | | ... ] or [ ... | | A ]
|
|
--- | `enums.B` # Components on the second section. [ | B | ... ] or [ ... | B | ]
|
|
--- | `enums.C` # Components on the third section. [ | | C ... ] or [ ... C | | ]
|
|
|
|
--==================--
|
|
-- Type Declaration --
|
|
--==================--
|
|
|
|
local Side = { LEFT = 0, RIGHT = 1 }
|
|
local SeparatorType = { OUTER = 0, INNER = 1 }
|
|
local ComponentType = { A = 0, B = 1, C = 2 }
|
|
|
|
os.setlocale("")
|
|
|
|
--=========================--
|
|
-- Variable Initialization --
|
|
--=========================--
|
|
|
|
local section_separator_open
|
|
local section_separator_close
|
|
|
|
local inverse_separator_open
|
|
local inverse_separator_close
|
|
|
|
local part_separator_open
|
|
local part_separator_close
|
|
|
|
local separator_style = { bg = nil, fg = nil }
|
|
|
|
local style_a
|
|
local style_b
|
|
local style_c
|
|
|
|
local style_a_normal_bg
|
|
local style_a_select_bg
|
|
local style_a_un_set_bg
|
|
|
|
local permissions_t_fg
|
|
local permissions_r_fg
|
|
local permissions_w_fg
|
|
local permissions_x_fg
|
|
local permissions_s_fg
|
|
|
|
local tab_width
|
|
local tab_use_inverse
|
|
|
|
local selected_icon
|
|
local copied_icon
|
|
local cut_icon
|
|
|
|
local selected_fg
|
|
local copied_fg
|
|
local cut_fg
|
|
|
|
local task_total_icon
|
|
local task_succ_icon
|
|
local task_fail_icon
|
|
local task_found_icon
|
|
local task_processed_icon
|
|
|
|
local task_total_fg
|
|
local task_succ_fg
|
|
local task_fail_fg
|
|
local task_found_fg
|
|
local task_processed_fg
|
|
|
|
local show_background
|
|
|
|
local display_header_line
|
|
local display_status_line
|
|
|
|
local section_order = { "section_a", "section_b", "section_c" }
|
|
|
|
--=================--
|
|
-- Component Setup --
|
|
--=================--
|
|
|
|
--- Sets the background of style_a according to the tab's mode.
|
|
--- @param mode Mode The mode of the active tab.
|
|
--- @see cx.active.mode To get the active tab's mode.
|
|
local function set_mode_style(mode)
|
|
if mode.is_select then
|
|
style_a.bg = style_a_select_bg
|
|
elseif mode.is_unset then
|
|
style_a.bg = style_a_un_set_bg
|
|
else
|
|
style_a.bg = style_a_normal_bg
|
|
end
|
|
end
|
|
|
|
--- Sets the style of the separator according to the parameters.
|
|
--- While selecting component type of both previous and following components,
|
|
--- always think separator is in middle of two components
|
|
--- and previous component is in left side and following component is in right side.
|
|
--- Thus, side of component does not important when choosing these two components.
|
|
--- @param separator_type SeparatorType Where will there be a separator in the section.
|
|
--- @param component_type ComponentType Which section component will be in [ a | b | c ].
|
|
local function set_separator_style(separator_type, component_type)
|
|
separator_style = { bg = nil, fg = nil }
|
|
if separator_type == SeparatorType.OUTER then
|
|
if component_type == ComponentType.A then
|
|
separator_style.bg = style_b.bg
|
|
separator_style.fg = style_a.bg
|
|
elseif component_type == ComponentType.B then
|
|
separator_style.bg = style_c.bg
|
|
separator_style.fg = style_b.bg
|
|
else
|
|
separator_style.fg = style_c.bg
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
end
|
|
else
|
|
if component_type == ComponentType.A then
|
|
separator_style.bg = style_a.bg
|
|
separator_style.fg = style_a.fg
|
|
elseif component_type == ComponentType.B then
|
|
separator_style.bg = style_b.bg
|
|
separator_style.fg = style_b.fg
|
|
else
|
|
separator_style.bg = style_c.bg
|
|
separator_style.fg = style_c.fg
|
|
end
|
|
end
|
|
end
|
|
|
|
--- Sets the style of the component according to the its type.
|
|
--- @param component Span Component that will be styled.
|
|
--- @param component_type ComponentType Which section component will be in [ a | b | c ].
|
|
--- @see Style To see how to style, in Yazi's documentation.
|
|
local function set_component_style(component, component_type)
|
|
if component_type == ComponentType.A then
|
|
component:style(style_a):bold()
|
|
elseif component_type == ComponentType.B then
|
|
component:style(style_b)
|
|
else
|
|
component:style(style_c)
|
|
end
|
|
end
|
|
|
|
--- Connects component to a separator.
|
|
--- @param component Span Component that will be connected to separator.
|
|
--- @param side Side Left or right side of the either header-line or status-line.
|
|
--- @param separator_type SeparatorType Where will there be a separator in the section.
|
|
--- @return Line line A Line which has component and separator.
|
|
local function connect_separator(component, side, separator_type)
|
|
local open, close
|
|
if separator_type == SeparatorType.OUTER then
|
|
open = ui.Span(section_separator_open)
|
|
close = ui.Span(section_separator_close)
|
|
else
|
|
open = ui.Span(part_separator_open)
|
|
close = ui.Span(part_separator_close)
|
|
end
|
|
|
|
open:style(separator_style)
|
|
close:style(separator_style)
|
|
|
|
if side == Side.LEFT then
|
|
return ui.Line { component, close }
|
|
else
|
|
return ui.Line { open, component }
|
|
end
|
|
end
|
|
|
|
--- Creates a component from given string according to other parameters.
|
|
--- @param string string The text which will be shown inside of the component.
|
|
--- @param component_type ComponentType Which section component will be in [ a | b | c ].
|
|
--- @return Line line Customized Line which follows desired style of the parameters.
|
|
--- @see set_mode_style To know how mode style selected.
|
|
--- @see set_separator_style To know how separator style applied.
|
|
--- @see set_component_style To know how component style applied.
|
|
--- @see connect_separator To know how component and separator connected.
|
|
local function create_component_from_str(string, component_type)
|
|
local span = ui.Span(" " .. string .. " ")
|
|
set_mode_style(cx.active.mode)
|
|
set_component_style(span, component_type)
|
|
|
|
return ui.Line{span}
|
|
end
|
|
|
|
--- Creates a component from given Coloreds according to other parameters.
|
|
--- The component it created, can contain multiple strings with different foreground color.
|
|
--- @param coloreds Coloreds The array which contains an array which contains text which will be shown inside of the component and its foreground color.
|
|
--- @param component_type ComponentType Which section component will be in [ a | b | c ].
|
|
--- @return Line line Customized Line which follows desired style of the parameters.
|
|
--- @see set_mode_style To know how mode style selected.
|
|
--- @see set_separator_style To know how separator style applied.
|
|
--- @see set_component_style To know how component style applied.
|
|
--- @see connect_separator To know how component and separator connected.
|
|
local function create_component_from_coloreds(coloreds, component_type)
|
|
set_mode_style(cx.active.mode)
|
|
|
|
local spans = {}
|
|
for i, colored in ipairs(coloreds) do
|
|
local span = ui.Span(colored[1])
|
|
set_component_style(span, component_type)
|
|
span:fg(colored[2])
|
|
|
|
spans[i] = span
|
|
end
|
|
|
|
return ui.Line(spans)
|
|
end
|
|
|
|
--==================--
|
|
-- Helper Functions --
|
|
--==================--
|
|
|
|
--- Gets the file name from given file extension.
|
|
--- @param file_name string The name of a file whose extension will be taken.
|
|
--- @return string file_extension Extension of a file.
|
|
local function get_file_extension(file_name)
|
|
local extension = file_name:match("^.+%.(.+)$")
|
|
|
|
if extension == nil or extension == "" then
|
|
return "null"
|
|
else
|
|
return extension
|
|
end
|
|
end
|
|
|
|
--- Reverse the order of given array
|
|
--- @param array Line Array which wants to be reversed.
|
|
--- @return table reversed Reversed ordered given array.
|
|
local function reverse_order(array)
|
|
local reversed = {}
|
|
for i = #array, 1, -1 do
|
|
table.insert(reversed, array[i])
|
|
end
|
|
|
|
return reversed
|
|
end
|
|
|
|
--==================--
|
|
-- Getter Functions --
|
|
--==================--
|
|
|
|
local get = {}
|
|
|
|
--- Gets the hovered file's name of the current active tab.
|
|
--- @return string name Current active tab's hovered file's name.
|
|
function get:hovered_name()
|
|
local hovered = cx.active.current.hovered
|
|
if hovered then
|
|
return hovered.name
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--- Gets the hovered file's path of the current active tab.
|
|
--- @return string path Current active tab's hovered file's path.
|
|
function get:hovered_path()
|
|
local hovered = cx.active.current.hovered
|
|
if hovered then
|
|
return tostring(hovered.url)
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--- Gets the hovered file's size of the current active tab.
|
|
--- @return string size Current active tab's hovered file's size.
|
|
function get:hovered_size()
|
|
local hovered = cx.active.current.hovered
|
|
if hovered then
|
|
return ya.readable_size(hovered:size() or hovered.cha.length)
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--- Gets the hovered file's path of the current active tab.
|
|
--- @return string mime Current active tab's hovered file's path.
|
|
function get:hovered_mime()
|
|
local hovered = cx.active.current.hovered
|
|
if hovered then
|
|
return hovered:mime()
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--- Gets the hovered file's extension of the current active tab.
|
|
--- @param show_icon boolean Whether or not an icon will be shown.
|
|
--- @return string file_extension Current active tab's hovered file's extension.
|
|
function get:hovered_file_extension(show_icon)
|
|
local hovered = cx.active.current.hovered
|
|
|
|
if hovered then
|
|
local cha = hovered.cha
|
|
|
|
local name
|
|
if cha.is_dir then
|
|
name = "dir"
|
|
else
|
|
name = get_file_extension(hovered.url:name())
|
|
end
|
|
|
|
if show_icon then
|
|
local icon = hovered:icon().text
|
|
return icon .. " " .. name
|
|
else
|
|
return name
|
|
end
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--- Gets the path of the current active tab.
|
|
--- @return string path Current active tab's path.
|
|
function get:tab_path()
|
|
return cx.active.current.cwd
|
|
end
|
|
|
|
--- Gets the mode of active tab.
|
|
--- @return string mode Active tab's mode.
|
|
function get:tab_mode()
|
|
local mode = tostring(cx.active.mode):upper()
|
|
if mode == "UNSET" then
|
|
mode = "UN-SET"
|
|
end
|
|
|
|
return mode
|
|
end
|
|
|
|
--- Gets the number of files in the current active tab.
|
|
--- @return string num_files Number of files in the current active tab.
|
|
function get:tab_num_files()
|
|
return tostring(#cx.active.current.files)
|
|
end
|
|
|
|
--- Gets the cursor position in the current active tab.
|
|
--- @return string cursor_position Current active tab's cursor position.
|
|
function get:cursor_position()
|
|
local cursor = cx.active.current.cursor
|
|
local length = #cx.active.current.files
|
|
|
|
if length ~= 0 then
|
|
return string.format(" %2d/%-2d", cursor + 1, length)
|
|
else
|
|
return "0"
|
|
end
|
|
end
|
|
|
|
--- Gets the cursor position as percentage which is according to the number of files inside of current active tab.
|
|
--- @return string percentage Percentage of current active tab's cursor position and number of percentages.
|
|
function get:cursor_percentage()
|
|
local percentage = 0
|
|
local cursor = cx.active.current.cursor
|
|
local length = #cx.active.current.files
|
|
if cursor ~= 0 and length ~= 0 then
|
|
percentage = math.floor((cursor + 1) * 100 / length)
|
|
end
|
|
|
|
if percentage == 0 then
|
|
return " Top "
|
|
elseif percentage == 100 then
|
|
return " Bot "
|
|
else
|
|
return string.format("%3d%% ", percentage)
|
|
end
|
|
end
|
|
|
|
--- Gets the local date or time values.
|
|
--- @param format string Format for giving desired date or time values.
|
|
--- @return string date Date or time values.
|
|
--- @see os.date To see how format works.
|
|
function get:date(format)
|
|
return tostring(os.date(format))
|
|
end
|
|
|
|
--=====================--
|
|
-- Component Functions --
|
|
--=====================--
|
|
|
|
local create = {}
|
|
|
|
--- Creates and returns line component for tabs.
|
|
--- @param side Side Left or right side of the either header-line or status-line.
|
|
--- @return Line line Customized Line which contains tabs.
|
|
--- @see set_mode_style To know how mode style selected.
|
|
--- @see set_component_style To know how component style applied.
|
|
--- @see connect_separator To know how component and separator connected.
|
|
function create:tabs(side)
|
|
local tabs = #cx.tabs
|
|
local lines = {}
|
|
|
|
local in_side
|
|
if side == "left" then
|
|
in_side = Side.LEFT
|
|
else
|
|
in_side = Side.RIGHT
|
|
end
|
|
|
|
for i = 1, tabs do
|
|
local text = i
|
|
if tab_width > 2 then
|
|
text = ya.truncate(text .. " " .. cx.tabs[i]:name(), { max = tab_width })
|
|
end
|
|
|
|
separator_style = { bg = nil, fg = nil }
|
|
if i == cx.tabs.idx then
|
|
local span = ui.Span(" " .. text .. " ")
|
|
set_mode_style(cx.tabs[i].mode)
|
|
set_component_style(span, ComponentType.A)
|
|
|
|
separator_style.fg = style_a.bg
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
|
|
lines[#lines + 1] = connect_separator(span, in_side, SeparatorType.OUTER)
|
|
else
|
|
local span = ui.Span(" " .. text .. " ")
|
|
if show_background then
|
|
set_component_style(span, ComponentType.C)
|
|
else
|
|
span:style({ fg = style_c.fg })
|
|
end
|
|
|
|
if i == cx.tabs.idx - 1 then
|
|
set_mode_style(cx.tabs[i + 1].mode)
|
|
|
|
local open, close
|
|
if tab_use_inverse then
|
|
separator_style.fg = style_a.bg
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
|
|
open = ui.Span(inverse_separator_open)
|
|
close = ui.Span(inverse_separator_close)
|
|
else
|
|
separator_style.bg = style_a.bg
|
|
if show_background then
|
|
separator_style.fg = style_c.bg
|
|
end
|
|
|
|
open = ui.Span(section_separator_open)
|
|
close = ui.Span(section_separator_close)
|
|
end
|
|
|
|
open:style(separator_style)
|
|
close:style(separator_style)
|
|
|
|
if in_side == Side.LEFT then
|
|
lines[#lines + 1] = ui.Line { span, close }
|
|
else
|
|
lines[#lines + 1] = ui.Line { open, span }
|
|
end
|
|
else
|
|
separator_style.fg = style_c.fg
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
|
|
lines[#lines + 1] = connect_separator(span, in_side, SeparatorType.INNER)
|
|
end
|
|
end
|
|
end
|
|
|
|
if in_side == Side.RIGHT then
|
|
local lines_in_right = {}
|
|
for i = #lines, 1, -1 do
|
|
lines_in_right[#lines_in_right + 1] = lines[i]
|
|
end
|
|
|
|
return ui.Line(lines_in_right)
|
|
else
|
|
return ui.Line(lines)
|
|
end
|
|
end
|
|
|
|
--====================--
|
|
-- Coloreds Functions --
|
|
--====================--
|
|
|
|
local colorize = {}
|
|
|
|
--- Gets the hovered file's permissions of the current active tab.
|
|
--- @return Coloreds coloreds Current active tab's hovered file's permissions
|
|
function colorize:permissions()
|
|
local hovered = cx.active.current.hovered
|
|
|
|
if hovered then
|
|
local perm = hovered.cha:permissions()
|
|
|
|
local coloreds = {}
|
|
coloreds[1] = { " ", "black" }
|
|
|
|
for i = 1, #perm do
|
|
local c = perm:sub(i, i)
|
|
|
|
local fg = permissions_t_fg
|
|
if c == "-" then
|
|
fg = permissions_s_fg
|
|
elseif c == "r" then
|
|
fg = permissions_r_fg
|
|
elseif c == "w" then
|
|
fg = permissions_w_fg
|
|
elseif c == "x" or c == "s" or c == "S" or c == "t" or c == "T" then
|
|
fg = permissions_x_fg
|
|
end
|
|
|
|
coloreds[i + 1] = { c, fg }
|
|
end
|
|
|
|
coloreds[#perm + 2] = { " ", "black" }
|
|
|
|
return coloreds
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--- Gets the number of selected and yanked files of the active tab.
|
|
--- @return Coloreds coloreds Active tab's number of selected and yanked files.
|
|
function colorize:count()
|
|
local num_yanked = #cx.yanked
|
|
local num_selected = #cx.active.selected
|
|
|
|
local yanked_fg, yanked_icon
|
|
if cx.yanked.is_cut then
|
|
yanked_fg = cut_fg
|
|
yanked_icon = cut_icon
|
|
else
|
|
yanked_fg = copied_fg
|
|
yanked_icon = copied_icon
|
|
end
|
|
|
|
local coloreds = {
|
|
{ string.format(" %s %d ", selected_icon, num_selected), selected_fg },
|
|
{ string.format(" %s %d ", yanked_icon, num_yanked), yanked_fg }
|
|
}
|
|
|
|
return coloreds
|
|
end
|
|
|
|
--- Gets the number of task states.
|
|
--- @return Coloreds coloreds Number of task states.
|
|
function colorize:task_states()
|
|
local tasks = cx.tasks.progress
|
|
|
|
local coloreds = {
|
|
{ string.format(" %s %d ", task_total_icon, tasks.total), task_total_fg },
|
|
{ string.format(" %s %d ", task_succ_icon, tasks.succ), task_succ_fg },
|
|
{ string.format(" %s %d ", task_fail_icon, tasks.fail), task_fail_fg }
|
|
}
|
|
|
|
return coloreds
|
|
end
|
|
|
|
--- Gets the number of task workloads.
|
|
--- @return Coloreds coloreds Number of task workloads.
|
|
function colorize:task_workload()
|
|
local tasks = cx.tasks.progress
|
|
|
|
local coloreds = {
|
|
{ string.format(" %s %d ", task_found_icon, tasks.found), task_found_fg },
|
|
{ string.format(" %s %d ", task_processed_icon, tasks.processed), task_processed_fg },
|
|
}
|
|
|
|
return coloreds
|
|
end
|
|
|
|
--- Gets colored which contains string based component's string and desired foreground color.
|
|
--- @param component_name string String based component's name.
|
|
--- @param fg Color Desired foreground color.
|
|
--- @param params? table Array of parameters of string based component. It is optional.
|
|
--- @return Coloreds coloreds Array of solely array of string based component's string and desired foreground color.
|
|
function colorize:string_based_component(component_name, fg, params)
|
|
local getter = get[component_name]
|
|
|
|
if getter then
|
|
local output
|
|
if params then
|
|
output = getter(get, table.unpack(params))
|
|
else
|
|
output = getter()
|
|
end
|
|
|
|
|
|
if output ~= nil and output ~= "" then
|
|
return { { output, fg } }
|
|
else
|
|
return ""
|
|
end
|
|
else
|
|
return ""
|
|
end
|
|
end
|
|
|
|
--===============--
|
|
-- Configuration --
|
|
--===============--
|
|
|
|
--- Connects given components with configured separator
|
|
--- @param section_a_components table Components array whose components are in section-a of either side.
|
|
--- @param section_b_components table Components array whose components are in section-b of either side.
|
|
--- @param section_c_components table Components array whose components are in section-c of either side.
|
|
--- @param side Side Left or right side of the either header-line or status-line.
|
|
--- @return table section_a_line_components Array of components whose components are connected to separator and are in section-a of either side.
|
|
--- @return table section_b_line_components Array of components whose components are connected to separator and are in section-b of either side.
|
|
--- @return table section_c_line_components Array of components whose components are connected to separator and are in section-c of either side.
|
|
local function config_separator(section_a_components, section_b_components, section_c_components, side)
|
|
local num_section_a_components = #section_a_components
|
|
local num_section_b_components = #section_b_components
|
|
local num_section_c_components = #section_c_components
|
|
|
|
local section_a_line_components = {}
|
|
for i, component in ipairs(section_a_components) do
|
|
if component[2] == true then
|
|
separator_style = { bg = nil, fg = nil }
|
|
|
|
local open, close
|
|
if i ~= num_section_a_components then
|
|
separator_style.bg = style_a.bg
|
|
separator_style.fg = style_a.fg
|
|
|
|
open = ui.Span(part_separator_open)
|
|
close = ui.Span(part_separator_close)
|
|
else
|
|
separator_style.fg = style_a.bg
|
|
|
|
if num_section_b_components == 0 and num_section_c_components == 0 then
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
elseif num_section_b_components == 0 then
|
|
separator_style.bg = style_c.bg
|
|
else
|
|
separator_style.bg = style_b.bg
|
|
end
|
|
|
|
open = ui.Span(section_separator_open)
|
|
close = ui.Span(section_separator_close)
|
|
end
|
|
|
|
open:style(separator_style)
|
|
close:style(separator_style)
|
|
|
|
if side == Side.LEFT then
|
|
section_a_line_components[i] = ui.Line { component[1], close }
|
|
else
|
|
section_a_line_components[i] = ui.Line { open, component[1] }
|
|
end
|
|
else
|
|
if side == Side.LEFT then
|
|
section_a_line_components[i] = component[1]
|
|
else
|
|
section_a_line_components[i] = component[1]
|
|
end
|
|
end
|
|
end
|
|
|
|
local section_b_line_components = {}
|
|
for i, component in ipairs(section_b_components) do
|
|
if component[2] == true then
|
|
separator_style = { bg = nil, fg = nil }
|
|
|
|
local open, close
|
|
if i ~= num_section_b_components then
|
|
separator_style.bg = style_b.bg
|
|
separator_style.fg = style_b.fg
|
|
|
|
open = ui.Span(part_separator_open)
|
|
close = ui.Span(part_separator_close)
|
|
else
|
|
separator_style.fg = style_b.bg
|
|
|
|
if num_section_c_components == 0 then
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
else
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
|
|
open = ui.Span(section_separator_open)
|
|
close = ui.Span(section_separator_close)
|
|
end
|
|
|
|
open:style(separator_style)
|
|
close:style(separator_style)
|
|
|
|
if side == Side.LEFT then
|
|
section_b_line_components[i] = ui.Line { component[1], close }
|
|
else
|
|
section_b_line_components[i] = ui.Line { open, component[1] }
|
|
end
|
|
else
|
|
if side == Side.LEFT then
|
|
section_b_line_components[i] = component[1]
|
|
else
|
|
section_b_line_components[i] = component[1]
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
local section_c_line_components = {}
|
|
for i, component in ipairs(section_c_components) do
|
|
if component[2] == true then
|
|
separator_style = { bg = nil, fg = nil }
|
|
|
|
local open, close
|
|
if i ~= num_section_c_components then
|
|
separator_style.bg = style_c.bg
|
|
separator_style.fg = style_c.fg
|
|
|
|
open = ui.Span(part_separator_open)
|
|
close = ui.Span(part_separator_close)
|
|
else
|
|
separator_style.fg = style_c.bg
|
|
|
|
if show_background then
|
|
separator_style.bg = style_c.bg
|
|
end
|
|
|
|
open = ui.Span(section_separator_open)
|
|
close = ui.Span(section_separator_close)
|
|
end
|
|
|
|
open:style(separator_style)
|
|
close:style(separator_style)
|
|
|
|
if side == Side.LEFT then
|
|
section_c_line_components[i] = ui.Line { component[1], close }
|
|
else
|
|
section_c_line_components[i] = ui.Line { open, component[1] }
|
|
end
|
|
else
|
|
if side == Side.LEFT then
|
|
section_c_line_components[i] = component[1]
|
|
else
|
|
section_c_line_components[i] = component[1]
|
|
end
|
|
end
|
|
end
|
|
|
|
return section_a_line_components, section_b_line_components, section_c_line_components
|
|
end
|
|
|
|
--- Automatically creates and configures either left or right side according to their config.
|
|
--- @param side Config Configuration of either left or right side.
|
|
--- @return table section_a_components Components array whose components are in section-a of either side.
|
|
--- @return table section_b_components Components array whose components are in section-b of either side.
|
|
--- @return table section_c_components Components array whose components are in section-c of either side.
|
|
local function config_side(side)
|
|
local section_a_components = {}
|
|
local section_b_components = {}
|
|
local section_c_components = {}
|
|
|
|
for _, section in ipairs(section_order) do
|
|
local components = side[section]
|
|
|
|
local in_section, section_components
|
|
if section == "section_a" then
|
|
in_section = ComponentType.A
|
|
section_components = section_a_components
|
|
elseif section == "section_b" then
|
|
in_section = ComponentType.B
|
|
section_components = section_b_components
|
|
else
|
|
in_section = ComponentType.C
|
|
section_components = section_c_components
|
|
end
|
|
|
|
for _, component in ipairs(components) do
|
|
if component.type == "string" then
|
|
if component.custom then
|
|
section_components[#section_components + 1] = { create_component_from_str(component.name, in_section), true }
|
|
else
|
|
local getter = get[component.name]
|
|
|
|
if getter then
|
|
local output
|
|
if component.params then
|
|
output = getter(get, table.unpack(component.params))
|
|
else
|
|
output = getter()
|
|
end
|
|
|
|
if output ~= nil and output ~= "" then
|
|
section_components[#section_components + 1] = { create_component_from_str(output, in_section), true }
|
|
end
|
|
end
|
|
end
|
|
elseif component.type == "coloreds" then
|
|
if component.custom then
|
|
section_components[#section_components + 1] = { create_component_from_coloreds(component.name, in_section), true }
|
|
else
|
|
local colorizer = colorize[component.name]
|
|
|
|
if colorizer then
|
|
local output
|
|
if component.params then
|
|
output = colorizer(colorize, table.unpack(component.params))
|
|
else
|
|
output = colorizer()
|
|
end
|
|
|
|
if output ~= nil and output ~= "" then
|
|
section_components[#section_components + 1] = { create_component_from_coloreds(output, in_section), true }
|
|
end
|
|
end
|
|
end
|
|
elseif component.type == "line" then
|
|
if component.custom then
|
|
section_components[#section_components + 1] = component.name
|
|
else
|
|
local creator = create[component.name]
|
|
|
|
if creator then
|
|
local output
|
|
if component.params then
|
|
output = creator(create, table.unpack(component.params))
|
|
else
|
|
output = creator()
|
|
end
|
|
|
|
if output then
|
|
section_components[#section_components + 1] = { output, false }
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return section_a_components, section_b_components, section_c_components
|
|
end
|
|
|
|
--- Automatically creates and configures either header-line or status-line.
|
|
--- @param side Config Configuration of either left or right side.
|
|
--- @return table left_components Components array whose components are in left side of the line.
|
|
--- @return table right_components Components array whose components are in right side of the line.
|
|
local function config_line(side, in_side)
|
|
local section_a_components, section_b_components, section_c_components = config_side(side)
|
|
|
|
local section_a_line_components, section_b_line_components, section_c_line_components = config_separator(section_a_components, section_b_components, section_c_components, in_side)
|
|
|
|
if in_side == Side.RIGHT then
|
|
section_a_line_components = reverse_order(section_a_line_components)
|
|
section_b_line_components = reverse_order(section_b_line_components)
|
|
section_c_line_components = reverse_order(section_c_line_components)
|
|
end
|
|
|
|
local section_a_line = ui.Line(section_a_line_components)
|
|
local section_b_line = ui.Line(section_b_line_components)
|
|
local section_c_line = ui.Line(section_c_line_components)
|
|
|
|
if in_side == Side.LEFT then
|
|
return ui.Line {section_a_line, section_b_line, section_c_line}
|
|
else
|
|
return ui.Line {section_c_line, section_b_line, section_a_line}
|
|
end
|
|
end
|
|
|
|
--- Checks if either header-line or status-line contains components.
|
|
--- @param line Config Configuration of either header-line or status-line.
|
|
--- @return boolean show_line Returns yes if it contains components, otherwise returns no.
|
|
local function show_line(line)
|
|
local total_components = 0
|
|
|
|
for _, side in pairs(line) do
|
|
for _, section in pairs(side) do
|
|
total_components = total_components + #section
|
|
end
|
|
end
|
|
|
|
return total_components ~= 0
|
|
end
|
|
|
|
--- Creates and configures paragraph which is used as left or right of either
|
|
--- header-line or status-line.
|
|
--- @param area Rect The area where paragraph will be placed in.
|
|
--- @param line? Line The line which used in paragraph. It is optional.
|
|
--- @return Paragraph paragraph Configured parapgraph.
|
|
local function config_paragraph(area, line)
|
|
local line_array = { line } or {}
|
|
if show_background then
|
|
return ui.Paragraph(area, line_array):style(style_c)
|
|
else
|
|
return ui.Paragraph(area, line_array)
|
|
end
|
|
end
|
|
|
|
return {
|
|
setup = function(_, config)
|
|
section_separator_open = config.section_separator.open
|
|
section_separator_close = config.section_separator.close
|
|
|
|
inverse_separator_open = config.inverse_separator.open
|
|
inverse_separator_close = config.inverse_separator.close
|
|
|
|
part_separator_open = config.part_separator.open
|
|
part_separator_close = config.part_separator.close
|
|
|
|
style_a = { bg = config.style_a.bg_mode.normal, fg = config.style_a.fg }
|
|
style_b = config.style_b
|
|
style_c = config.style_c
|
|
|
|
style_a_normal_bg = config.style_a.bg_mode.normal
|
|
style_a_select_bg = config.style_a.bg_mode.select
|
|
style_a_un_set_bg = config.style_a.bg_mode.un_set
|
|
|
|
permissions_t_fg = config.permissions_t_fg
|
|
permissions_r_fg = config.permissions_r_fg
|
|
permissions_w_fg = config.permissions_w_fg
|
|
permissions_x_fg = config.permissions_x_fg
|
|
permissions_s_fg = config.permissions_s_fg
|
|
|
|
tab_width = config.tab_width
|
|
tab_use_inverse = config.tab_use_inverse
|
|
|
|
selected_icon = config.selected.icon
|
|
copied_icon = config.copied.icon
|
|
cut_icon = config.cut.icon
|
|
|
|
selected_fg = config.selected.fg
|
|
copied_fg = config.copied.fg
|
|
cut_fg = config.cut.fg
|
|
|
|
task_total_icon = config.total.icon
|
|
task_succ_icon = config.succ.icon
|
|
task_fail_icon = config.fail.icon
|
|
task_found_icon = config.found.icon
|
|
task_processed_icon = config.processed.icon
|
|
|
|
task_total_fg = config.total.fg
|
|
task_succ_fg = config.succ.fg
|
|
task_fail_fg = config.fail.fg
|
|
task_found_fg = config.found.fg
|
|
task_processed_fg = config.processed.fg
|
|
|
|
show_background = config.show_background
|
|
|
|
display_header_line = config.display_header_line
|
|
display_status_line = config.display_status_line
|
|
|
|
Progress.partial_render = function(self)
|
|
local progress = cx.tasks.progress
|
|
if progress.total == 0 then
|
|
return { config_paragraph(self.area) }
|
|
end
|
|
|
|
local gauge = ui.Gauge(self.area)
|
|
if progress.fail == 0 then
|
|
gauge = gauge:gauge_style(THEME.status.progress_normal)
|
|
else
|
|
gauge = gauge:gauge_style(THEME.status.progress_error)
|
|
end
|
|
|
|
local percent = 99
|
|
if progress.found ~= 0 then
|
|
percent = math.min(99, ya.round(progress.processed * 100 / progress.found))
|
|
end
|
|
|
|
local left = progress.total - progress.succ
|
|
return {
|
|
gauge
|
|
:percent(percent)
|
|
:label(ui.Span(string.format("%3d%%, %d left", percent, left)):style(THEME.status.progress_label)),
|
|
}
|
|
end
|
|
|
|
local header_number = 0
|
|
local status_number = 0
|
|
|
|
if display_header_line then
|
|
if show_line(config.header_line) then
|
|
Header.render = function(self, area)
|
|
self.area = area
|
|
|
|
local left_line = config_line(config.header_line.left, Side.LEFT)
|
|
local right_line = config_line(config.header_line.right, Side.RIGHT)
|
|
|
|
return {
|
|
config_paragraph(area, left_line),
|
|
ui.Paragraph(area, { right_line }):align(ui.Paragraph.RIGHT)
|
|
}
|
|
end
|
|
end
|
|
else
|
|
header_number = 1
|
|
function Header:render() return {} end
|
|
|
|
end
|
|
|
|
if display_status_line then
|
|
if show_line(config.status_line) then
|
|
Status.render = function(self, area)
|
|
self.area = area
|
|
|
|
local left_line = config_line(config.status_line.left, Side.LEFT)
|
|
local right_line = config_line(config.status_line.right, Side.RIGHT)
|
|
|
|
return {
|
|
config_paragraph(area, left_line),
|
|
ui.Paragraph(area, { right_line }):align(ui.Paragraph.RIGHT),
|
|
table.unpack(Progress:render(area, right_line:width())),
|
|
}
|
|
end
|
|
end
|
|
else
|
|
status_number = 1
|
|
function Status:render() return {} end
|
|
|
|
end
|
|
|
|
if header_number + status_number ~= 0 then
|
|
local old_manager_render = Manager.render
|
|
function Manager:render(area)
|
|
return old_manager_render(self, ui.Rect { x = area.x, y = area.y - header_number, w = area.w, h = area.h + header_number + status_number })
|
|
end
|
|
end
|
|
end,
|
|
}
|