summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Heinrich <christoph.heinrich@student.tugraz.at>2022-06-20 23:26:33 +0200
committerDudemanguy <random342@airmail.cc>2023-10-07 22:45:50 +0000
commited8a919812974307c68d5238a95322a137f14545 (patch)
treed61eda2500116d2a580eb442c11ebab944c0b53c
parent659353b7d6e9862d7d5b92d99548144e47cc72c9 (diff)
downloadmpv-ed8a919812974307c68d5238a95322a137f14545.tar.bz2
mpv-ed8a919812974307c68d5238a95322a137f14545.tar.xz
console: show completion suggestions as table
Completion suggestions are now nicely formatted into a table. Maximum width of the table is estimated based on OSD size and font size. This requires a new scaling factor option `font_hw_ratio`. A factor of 2.15 works great for me, but the default is 2.0 to avoid problems with other fonts. The space between columns is automatically adjusted to be between 2 and 8 spaces. It tries to use as few rows as possible.
-rw-r--r--DOCS/man/console.rst12
-rw-r--r--player/lua/console.lua85
2 files changed, 87 insertions, 10 deletions
diff --git a/DOCS/man/console.rst b/DOCS/man/console.rst
index 681b7e5da1..cfcc643323 100644
--- a/DOCS/man/console.rst
+++ b/DOCS/man/console.rst
@@ -135,8 +135,9 @@ Configurable Options
``font``
Default: unset (picks a hardcoded font depending on detected platform)
- Set the font used for the REPL and the console. This probably doesn't
- have to be a monospaced font.
+ Set the font used for the REPL and the console.
+ This has to be a monospaced font for the completion suggestions to be
+ aligned correctly.
``font_size``
Default: 16
@@ -153,3 +154,10 @@ Configurable Options
Default: true
Remove duplicate entries in history as to only keep the latest one.
+ multiplied by "scale."
+
+``font_hw_ratio``
+ Default: 2.0
+
+ The ratio of font height to font width.
+ Adjusts table width of completion suggestions.
diff --git a/player/lua/console.lua b/player/lua/console.lua
index 107f80bfe1..6ff9f56f4d 100644
--- a/player/lua/console.lua
+++ b/player/lua/console.lua
@@ -21,8 +21,8 @@ local opts = {
-- All drawing is scaled by this value, including the text borders and the
-- cursor. Change it if you have a high-DPI display.
scale = 1,
- -- Set the font used for the REPL and the console. This probably doesn't
- -- have to be a monospaced font.
+ -- Set the font used for the REPL and the console.
+ -- This has to be a monospaced font.
font = "",
-- Set the font size used for the REPL and the console. This will be
-- multiplied by "scale".
@@ -30,6 +30,9 @@ local opts = {
border_size = 1,
-- Remove duplicate entries in history as to only keep the latest one.
history_dedup = true,
+ -- The ratio of font height to font width.
+ -- Adjusts table width of completion suggestions.
+ font_hw_ratio = 2.0,
}
function detect_platform()
@@ -136,6 +139,70 @@ function ass_escape(str)
return str
end
+-- Takes a list of strings and a max width in characters
+-- returns a string containing the formatted table
+function format_table(list, width_max)
+ if #list == 0 then
+ return ''
+ end
+
+ local spaces_min = 2
+ local spaces_max = 8
+ local list_size = #list
+ local column_count = 1
+ local row_count = list_size
+ local column_widths
+ -- total width without spacing
+ local width_total = 0
+
+ -- use as many columns as possible
+ for rows = 1, list_size do
+ local columns = math.ceil(list_size / rows)
+ column_widths = {}
+ width_total = 0
+
+ -- find out width of each column
+ for column = 1, columns do
+ local width = 0
+ for row = 1, rows do
+ local i = row + (column - 1) * rows
+ if i > #list then break end
+ local len = list[i]:len()
+ if width < len then
+ width = len
+ end
+ end
+ column_widths[column] = width
+ width_total = width_total + width
+ end
+
+ if width_total + columns * spaces_min <= width_max then
+ row_count = rows
+ column_count = columns
+ break
+ end
+ end
+
+ local spaces = math.floor((width_max - width_total) / (column_count - 1))
+ spaces = math.max(spaces_min, math.min(spaces_max, spaces))
+ local spacing = column_count > 1 and string.format('%' .. spaces .. 's', ' ') or ''
+
+ local rows = {}
+ for row = 1, row_count do
+ local columns = {}
+ for column = 1, column_count do
+ local i = row + (column - 1) * row_count
+ if i > #list then break end
+ local format_string = column == column_count and '%s'
+ or '%-' .. column_widths[column] .. 's'
+ columns[column] = string.format(format_string, list[i])
+ end
+ -- first row is at the bottom
+ rows[row_count - row + 1] = table.concat(columns, spacing)
+ end
+ return table.concat(rows, '\n')
+end
+
-- Render the REPL and console as an ASS OSD
function update()
pending_update = false
@@ -194,16 +261,18 @@ function update()
log_ass = log_ass .. style .. log_buffer[i].style .. ass_escape(log_buffer[i].text)
end
- local suggestion_ass = ''
- for _, l in ipairs(suggestion_buffer) do
- suggestion_ass = suggestion_ass .. style .. styles.suggestion .. ass_escape(l)
- end
+ -- estimate how many characters fit in a line
+ local width_max = math.ceil(screenx / opts.font_size * opts.font_hw_ratio)
+ local suggestions = ass_escape(format_table(suggestion_buffer, width_max))
+ local suggestion_ass = style .. styles.suggestion .. suggestions
ass:new_event()
ass:an(1)
ass:pos(2, screeny - 2 - global_margins.b * screeny)
ass:append(log_ass .. '\\N')
- ass:append(suggestion_ass)
+ if #suggestions > 0 then
+ ass:append(suggestion_ass .. '\\N')
+ end
ass:append(style .. '> ' .. before_cur)
ass:append(cglyph)
ass:append(style .. after_cur)
@@ -599,7 +668,7 @@ function complete()
table.sort(completions)
suggestion_buffer = {}
for i, completion in ipairs(completions) do
- suggestion_buffer[i] = completion .. '\n'
+ suggestion_buffer[i] = completion
end
end