-- -- fancy-prompt.lua: the fancy multiline prompt you probably want -- -- Copyright (c) 2016, Přemysl Janouch -- -- Permission to use, copy, modify, and/or distribute this software for any -- purpose with or without fee is hereby granted. -- -- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY -- SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION -- OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN -- CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -- -- Beware that it is a hack and only goes about 90% of the way, which is why -- this functionality is only available as a plugin in the first place -- (well, and also for customizability). -- -- The biggest problem is that the way we work with Readline is incompatible -- with multiline prompts, and normal newlines just don't work. This is being -- circumvented by using an overflowing single-line prompt with a specially -- crafted character in the rightmost column that prevents the bar's background -- from spilling all over the last line. -- -- There is also a problem with C-r search rendering not clearing out the -- background but to really fix that mode, we'd have to fully reimplement it -- since its alternative prompt very often gets overriden by accident anyway. degesch.hook_prompt (function (hook) local current = degesch.current_buffer local chan = current.channel local s = current.server local bg_color = "255" local current_n = 0 local active = "" for i, buffer in ipairs (degesch.buffers) do if buffer == current then current_n = i elseif buffer.new_messages_count ~= buffer.new_unimportant_count then if active ~= "" then active = active .. "," end if buffer.highlighted then active = active .. "!" bg_color = "224" end active = active .. i end end if active ~= "" then active = "(" .. active .. ")" end local x = current_n .. ":" .. current.name if chan and chan.users_len ~= 0 then local params = "" for mode, param in pairs (chan.param_modes) do params = params .. " +" .. mode .. " " .. param end local modes = chan.no_param_modes .. params:sub (3) if modes ~= "" then x = x .. "(+" .. modes .. ")" end x = x .. "{" .. chan.users_len .. "}" end if current.hide_unimportant then x = x .. "" end local lines, cols = degesch.get_screen_size () x = x .. " " .. active .. string.rep (" ", cols) -- Readline seems to be broken and completely corrupts the prompt -- (tested on 7.0.003 Archlinux, 7.0-5 Debian buster) x = x:gsub("[\128-\255]", "?") -- Cut off extra characters and apply formatting, including the hack. -- Note that this doesn't count with full-width or zero-width characters. local overflow = utf8.offset (x, cols - 1) if overflow then x = x:sub (1, overflow) end x = "\x01\x1b[0;4;1;38;5;16m\x1b[48;5;" .. bg_color .. "m\x02" .. x .. "\x01\x1b[0;4;1;7;38;5;" .. bg_color .. "m\x02 \x01\x1b[0;1m\x02" local user_prefix = function (chan, user) for i, chan_user in ipairs (chan.users) do if chan_user.user == user then return chan_user.prefixes end end return "" end if s then x = x .. "[" local state = s.state if state == "disconnected" or state == "connecting" then x = x .. "(" .. state .. ")" elseif state ~= "registered" then x = x .. "(unregistered)" else local user, modes = s.user, s.user_mode if chan then x = x .. user_prefix (chan, user) end x = x .. user.nickname if modes ~= "" then x = x .. "(" .. modes .. ")" end end x = x .. "] " else -- There needs to be at least one character so that the cursor -- doesn't get damaged by our hack in that last column x = x .. "> " end return x end)