cbc4041746
the fact this even worked in vertical mode was only due to a theming edge case.
159 lines
5.9 KiB
Python
159 lines
5.9 KiB
Python
"""
|
|
Module defining the global info bar
|
|
|
|
This window is the one listing the current opened tabs in poezio.
|
|
The GlobalInfoBar can be either horizontal or vertical
|
|
(VerticalGlobalInfoBar).
|
|
"""
|
|
import curses
|
|
import itertools
|
|
import logging
|
|
|
|
from typing import List, Optional
|
|
|
|
from poezio.config import config
|
|
from poezio.windows.base_wins import Win
|
|
from poezio.theming import get_theme, to_curses_attr
|
|
from poezio.common import unique_prefix_of
|
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
|
class GlobalInfoBar(Win):
|
|
__slots__ = ('core')
|
|
|
|
def __init__(self, core) -> None:
|
|
Win.__init__(self)
|
|
self.core = core
|
|
|
|
def refresh(self) -> None:
|
|
log.debug('Refresh: %s', self.__class__.__name__)
|
|
self._win.erase()
|
|
theme = get_theme()
|
|
self.addstr(0, 0, "[",
|
|
to_curses_attr(theme.COLOR_INFORMATION_BAR))
|
|
|
|
show_names = config.getbool('show_tab_names')
|
|
show_nums = config.getbool('show_tab_numbers')
|
|
use_nicks = config.getbool('use_tab_nicks')
|
|
show_inactive = config.getbool('show_inactive_tabs')
|
|
unique_prefix_tab_names = config.getbool('unique_prefix_tab_names')
|
|
|
|
if unique_prefix_tab_names:
|
|
unique_prefixes: List[Optional[str]] = [None] * len(self.core.tabs)
|
|
sorted_tab_indices = sorted(
|
|
(str(tab.name), i)
|
|
for i, tab in enumerate(self.core.tabs)
|
|
)
|
|
prev_name = ""
|
|
for (name, i), next_item in itertools.zip_longest(
|
|
sorted_tab_indices, sorted_tab_indices[1:]):
|
|
# TODO: should this maybe use something smarter than .lower()?
|
|
# something something stringprep?
|
|
name = name.lower()
|
|
prefix_prev = unique_prefix_of(name, prev_name)
|
|
if next_item is not None:
|
|
prefix_next = unique_prefix_of(name, next_item[0].lower())
|
|
else:
|
|
prefix_next = name[0]
|
|
|
|
# to be unique, we have to use the longest prefix
|
|
if len(prefix_next) > len(prefix_prev):
|
|
prefix = prefix_next
|
|
else:
|
|
prefix = prefix_prev
|
|
|
|
unique_prefixes[i] = prefix
|
|
prev_name = name
|
|
|
|
for nb, tab in enumerate(self.core.tabs):
|
|
if not tab:
|
|
continue
|
|
color = tab.color
|
|
if not show_inactive and color is theme.COLOR_TAB_NORMAL and (
|
|
tab.priority < 0):
|
|
continue
|
|
try:
|
|
if show_nums or not show_names:
|
|
self.addstr("%s" % str(nb), to_curses_attr(color))
|
|
if show_names:
|
|
self.addstr(' ', to_curses_attr(color))
|
|
if show_names:
|
|
if unique_prefix_tab_names:
|
|
self.addstr(unique_prefixes[nb], to_curses_attr(color))
|
|
elif use_nicks:
|
|
self.addstr("%s" % str(tab.get_nick()),
|
|
to_curses_attr(color))
|
|
else:
|
|
self.addstr("%s" % tab.name, to_curses_attr(color))
|
|
self.addstr("|",
|
|
to_curses_attr(theme.COLOR_INFORMATION_BAR))
|
|
except: # end of line
|
|
break
|
|
(y, x) = self._win.getyx()
|
|
self.addstr(y, x - 1, '] ',
|
|
to_curses_attr(theme.COLOR_INFORMATION_BAR))
|
|
(y, x) = self._win.getyx()
|
|
remaining_size = self.width - x
|
|
self.addnstr(' ' * remaining_size, remaining_size,
|
|
to_curses_attr(theme.COLOR_INFORMATION_BAR))
|
|
self._refresh()
|
|
|
|
|
|
class VerticalGlobalInfoBar(Win):
|
|
__slots__ = ('core')
|
|
|
|
def __init__(self, core, scr) -> None:
|
|
Win.__init__(self)
|
|
self.core = core
|
|
self._win = scr
|
|
|
|
def refresh(self) -> None:
|
|
height, width = self._win.getmaxyx()
|
|
self._win.erase()
|
|
sorted_tabs = [tab for tab in self.core.tabs if tab]
|
|
theme = get_theme()
|
|
if not config.getbool('show_inactive_tabs'):
|
|
sorted_tabs = [
|
|
tab for tab in sorted_tabs
|
|
if (
|
|
tab.vertical_color != theme.COLOR_VERTICAL_TAB_NORMAL or
|
|
tab.priority > 0
|
|
)
|
|
]
|
|
nb_tabs = len(sorted_tabs)
|
|
use_nicks = config.getbool('use_tab_nicks')
|
|
if nb_tabs >= height:
|
|
# TODO: As sorted_tabs filters out gap tabs this ensures pos is
|
|
# always set, preventing UnboundLocalError. Now is this how this
|
|
# should be fixed.
|
|
pos = 0
|
|
for y, tab in enumerate(sorted_tabs):
|
|
if tab.vertical_color == theme.COLOR_VERTICAL_TAB_CURRENT:
|
|
pos = y
|
|
break
|
|
# center the current tab as much as possible
|
|
if pos < height // 2:
|
|
sorted_tabs = sorted_tabs[:height]
|
|
elif nb_tabs - pos <= height // 2:
|
|
sorted_tabs = sorted_tabs[-height:]
|
|
else:
|
|
sorted_tabs = sorted_tabs[pos - height // 2:pos + height // 2]
|
|
asc_sort = (config.getstr('vertical_tab_list_sort') == 'asc')
|
|
for y, tab in enumerate(sorted_tabs):
|
|
color = tab.vertical_color
|
|
if asc_sort:
|
|
y = height - y - 1
|
|
self.addstr(y, 0, "%2d" % tab.nb,
|
|
to_curses_attr(theme.COLOR_VERTICAL_TAB_NUMBER))
|
|
self.addstr('.')
|
|
if use_nicks:
|
|
self.addnstr("%s" % tab.get_nick(), width - 4,
|
|
to_curses_attr(color))
|
|
else:
|
|
self.addnstr("%s" % tab.name, width - 4, to_curses_attr(color))
|
|
separator = to_curses_attr(theme.COLOR_VERTICAL_SEPARATOR)
|
|
self._win.attron(separator)
|
|
self._win.vline(0, width - 1, curses.ACS_VLINE, height)
|
|
self._win.attroff(separator)
|
|
self._refresh()
|