Use DisplayLine for menu choices
This commit is contained in:
parent
27606f7a75
commit
c54e6738b9
|
@ -1406,12 +1406,12 @@ const CommandDesc menu_cmd = {
|
|||
return;
|
||||
}
|
||||
|
||||
Vector<String> choices;
|
||||
Vector<DisplayLine> choices;
|
||||
Vector<String> commands;
|
||||
Vector<String> select_cmds;
|
||||
for (int i = 0; i < count; i += modulo)
|
||||
{
|
||||
choices.push_back(parser[i]);
|
||||
choices.push_back({ parser[i], {} });
|
||||
commands.push_back(parser[i+1]);
|
||||
if (with_select_cmds)
|
||||
select_cmds.push_back(parser[i+2]);
|
||||
|
|
|
@ -464,7 +464,7 @@ private:
|
|||
class Menu : public InputMode
|
||||
{
|
||||
public:
|
||||
Menu(InputHandler& input_handler, ConstArrayView<String> choices,
|
||||
Menu(InputHandler& input_handler, ConstArrayView<DisplayLine> choices,
|
||||
MenuCallback callback)
|
||||
: InputMode(input_handler),
|
||||
m_callback(callback), m_choices(choices.begin(), choices.end()),
|
||||
|
@ -479,8 +479,14 @@ public:
|
|||
|
||||
void on_key(Key key, KeepAlive keep_alive) override
|
||||
{
|
||||
auto match_filter = [this](const String& str) {
|
||||
return regex_match(str.begin(), str.end(), m_filter);
|
||||
auto match_filter = [this](const DisplayLine& choice) {
|
||||
for (auto& atom : choice)
|
||||
{
|
||||
const auto& contents = atom.content();
|
||||
if (regex_match(contents.begin(), contents.end(), m_filter))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
if (key == ctrl('m'))
|
||||
|
@ -564,7 +570,7 @@ public:
|
|||
private:
|
||||
MenuCallback m_callback;
|
||||
|
||||
using ChoiceList = Vector<String>;
|
||||
using ChoiceList = Vector<DisplayLine>;
|
||||
const ChoiceList m_choices;
|
||||
ChoiceList::const_iterator m_selected;
|
||||
|
||||
|
@ -823,10 +829,16 @@ private:
|
|||
const String& line = m_line_editor.line();
|
||||
m_completions = m_completer(context(), flags, line,
|
||||
line.byte_count_to(m_line_editor.cursor_pos()));
|
||||
CandidateList& candidates = m_completions.candidates;
|
||||
if (context().has_ui() and not candidates.empty())
|
||||
context().ui().menu_show(candidates, CharCoord{}, get_face("MenuForeground"),
|
||||
get_face("MenuBackground"), MenuStyle::Prompt);
|
||||
if (context().has_ui() and not m_completions.candidates.empty())
|
||||
{
|
||||
Vector<DisplayLine> items;
|
||||
for (auto& candidate : m_completions.candidates)
|
||||
items.push_back({ candidate, {} });
|
||||
context().ui().menu_show(items, CharCoord{},
|
||||
get_face("MenuForeground"),
|
||||
get_face("MenuBackground"),
|
||||
MenuStyle::Prompt);
|
||||
}
|
||||
} catch (runtime_error&) {}
|
||||
}
|
||||
|
||||
|
@ -1280,7 +1292,7 @@ void InputHandler::set_prompt_face(Face prompt_face)
|
|||
prompt->set_prompt_face(prompt_face);
|
||||
}
|
||||
|
||||
void InputHandler::menu(ConstArrayView<String> choices, MenuCallback callback)
|
||||
void InputHandler::menu(ConstArrayView<DisplayLine> choices, MenuCallback callback)
|
||||
{
|
||||
push_mode(new InputModes::Menu(*this, choices, callback));
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
// abort or validation with corresponding MenuEvent value
|
||||
// returns to normal mode after validation if callback does
|
||||
// not change the mode itself
|
||||
void menu(ArrayView<const String> choices, MenuCallback callback);
|
||||
void menu(ConstArrayView<DisplayLine> choices, MenuCallback callback);
|
||||
|
||||
// execute callback on next keypress and returns to normal mode
|
||||
// if callback does not change the mode itself
|
||||
|
|
|
@ -421,13 +421,13 @@ void InsertCompleter::menu_show()
|
|||
const CharCount tabstop = m_options["tabstop"].get<int>();
|
||||
const CharCount column = get_column(m_context.buffer(), tabstop,
|
||||
m_completions.begin);
|
||||
Vector<String> menu_entries;
|
||||
Vector<DisplayLine> menu_entries;
|
||||
for (auto& candidate : m_matching_candidates)
|
||||
{
|
||||
const String& entry = candidate.menu_entry.empty() ?
|
||||
candidate.completion : candidate.menu_entry;
|
||||
|
||||
menu_entries.push_back(expand_tabs(entry, tabstop, column));
|
||||
menu_entries.push_back({ expand_tabs(entry, tabstop, column), {} });
|
||||
}
|
||||
|
||||
m_context.ui().menu_show(menu_entries, menu_pos,
|
||||
|
|
|
@ -246,7 +246,8 @@ std::unique_ptr<UserInterface> create_local_ui(bool dummy_ui)
|
|||
{
|
||||
struct DummyUI : UserInterface
|
||||
{
|
||||
void menu_show(ConstArrayView<String>, CharCoord, Face, Face, MenuStyle) override {}
|
||||
void menu_show(ConstArrayView<DisplayLine>, CharCoord,
|
||||
Face, Face, MenuStyle) override {}
|
||||
void menu_select(int) override {}
|
||||
void menu_hide() override {}
|
||||
|
||||
|
|
|
@ -338,28 +338,29 @@ void add_str(WINDOW* win, StringView str)
|
|||
waddnstr(win, str.begin(), (int)str.length());
|
||||
}
|
||||
|
||||
void NCursesUI::draw_line(const DisplayLine& line, CharCount col_index,
|
||||
const Face& default_face) const
|
||||
static void draw_line(NCursesWin* window, const DisplayLine& line,
|
||||
CharCount col_index, CharCount max_column,
|
||||
const Face& default_face)
|
||||
{
|
||||
for (const DisplayAtom& atom : line)
|
||||
{
|
||||
set_face(m_window, atom.face, default_face);
|
||||
set_face(window, atom.face, default_face);
|
||||
|
||||
StringView content = atom.content();
|
||||
if (content.empty())
|
||||
continue;
|
||||
|
||||
const auto remaining_columns = m_dimensions.column - col_index;
|
||||
const auto remaining_columns = max_column - col_index;
|
||||
if (content.back() == '\n' and
|
||||
content.char_length() - 1 < remaining_columns)
|
||||
{
|
||||
add_str(m_window, content.substr(0, content.length()-1));
|
||||
waddch(m_window, ' ');
|
||||
add_str(window, content.substr(0, content.length()-1));
|
||||
waddch(window, ' ');
|
||||
}
|
||||
else
|
||||
{
|
||||
content = content.substr(0_char, remaining_columns);
|
||||
add_str(m_window, content);
|
||||
add_str(window, content);
|
||||
col_index += content.char_length();
|
||||
}
|
||||
}
|
||||
|
@ -377,7 +378,7 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer,
|
|||
{
|
||||
wmove(m_window, (int)line_index, 0);
|
||||
wclrtoeol(m_window);
|
||||
draw_line(line, 0, default_face);
|
||||
draw_line(m_window, line, 0, m_dimensions.column, default_face);
|
||||
++line_index;
|
||||
}
|
||||
|
||||
|
@ -402,7 +403,7 @@ void NCursesUI::draw_status(const DisplayLine& status_line,
|
|||
wbkgdset(m_window, COLOR_PAIR(get_color_pair(default_face)));
|
||||
wclrtoeol(m_window);
|
||||
|
||||
draw_line(status_line, 0, default_face);
|
||||
draw_line(m_window, status_line, 0, m_dimensions.column, default_face);
|
||||
|
||||
const auto mode_len = mode_line.length();
|
||||
const auto remaining = m_dimensions.column - status_line.length();
|
||||
|
@ -410,7 +411,7 @@ void NCursesUI::draw_status(const DisplayLine& status_line,
|
|||
{
|
||||
CharCount col = m_dimensions.column - mode_len;
|
||||
wmove(m_window, status_line_pos, (int)col);
|
||||
draw_line(mode_line, col, default_face);
|
||||
draw_line(m_window, mode_line, col, m_dimensions.column, default_face);
|
||||
}
|
||||
else if (remaining > 2)
|
||||
{
|
||||
|
@ -421,7 +422,7 @@ void NCursesUI::draw_status(const DisplayLine& status_line,
|
|||
|
||||
CharCount col = m_dimensions.column - remaining + 1;
|
||||
wmove(m_window, status_line_pos, (int)col);
|
||||
draw_line(trimmed_mode_line, col, default_face);
|
||||
draw_line(m_window, trimmed_mode_line, col, m_dimensions.column, default_face);
|
||||
}
|
||||
|
||||
if (m_set_title)
|
||||
|
@ -620,14 +621,12 @@ void NCursesUI::draw_menu()
|
|||
+ col;
|
||||
if (item_idx >= item_count)
|
||||
break;
|
||||
if (item_idx == m_selected_item)
|
||||
wattron(m_menu.win, COLOR_PAIR(menu_fg));
|
||||
|
||||
StringView item = m_items[item_idx].substr(0_char, column_width);
|
||||
add_str(m_menu.win, item);
|
||||
const CharCount pad = column_width - item.char_length();
|
||||
const DisplayLine& item = m_items[item_idx];
|
||||
draw_line(m_menu.win, item, 0, column_width,
|
||||
item_idx == m_selected_item ? m_menu_fg : m_menu_bg);
|
||||
const CharCount pad = column_width - item.length();
|
||||
add_str(m_menu.win, String{' ' COMMA pad});
|
||||
wattron(m_menu.win, COLOR_PAIR(menu_bg));
|
||||
}
|
||||
const bool is_mark = line >= mark_line and
|
||||
line < mark_line + mark_height;
|
||||
|
@ -639,7 +638,7 @@ void NCursesUI::draw_menu()
|
|||
m_dirty = true;
|
||||
}
|
||||
|
||||
void NCursesUI::menu_show(ConstArrayView<String> items,
|
||||
void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
|
||||
CharCoord anchor, Face fg, Face bg,
|
||||
MenuStyle style)
|
||||
{
|
||||
|
@ -664,8 +663,9 @@ void NCursesUI::menu_show(ConstArrayView<String> items,
|
|||
const CharCount maxlen = min((int)maxsize.column-2, 200);
|
||||
for (auto& item : items)
|
||||
{
|
||||
m_items.push_back(item.substr(0_char, maxlen).str());
|
||||
longest = max(longest, m_items.back().char_length());
|
||||
m_items.push_back(item);
|
||||
m_items.back().trim(0, maxlen, false);
|
||||
longest = max(longest, m_items.back().length());
|
||||
}
|
||||
longest += 1;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
bool is_key_available() override;
|
||||
Key get_key() override;
|
||||
|
||||
void menu_show(ConstArrayView<String> items,
|
||||
void menu_show(ConstArrayView<DisplayLine> items,
|
||||
CharCoord anchor, Face fg, Face bg,
|
||||
MenuStyle style) override;
|
||||
void menu_select(int selected) override;
|
||||
|
@ -54,8 +54,6 @@ public:
|
|||
private:
|
||||
void check_resize(bool force = false);
|
||||
void redraw();
|
||||
void draw_line(const DisplayLine& line, CharCount col_index,
|
||||
const Face& default_face) const;
|
||||
|
||||
NCursesWin* m_window = nullptr;
|
||||
|
||||
|
@ -77,7 +75,7 @@ private:
|
|||
void mark_dirty(const Window& win);
|
||||
|
||||
Window m_menu;
|
||||
Vector<String> m_items;
|
||||
Vector<DisplayLine> m_items;
|
||||
Face m_menu_fg;
|
||||
Face m_menu_bg;
|
||||
int m_selected_item = 0;
|
||||
|
|
|
@ -237,7 +237,7 @@ public:
|
|||
RemoteUI(int socket);
|
||||
~RemoteUI();
|
||||
|
||||
void menu_show(ConstArrayView<String> choices,
|
||||
void menu_show(ConstArrayView<DisplayLine> choices,
|
||||
CharCoord anchor, Face fg, Face bg,
|
||||
MenuStyle style) override;
|
||||
void menu_select(int selected) override;
|
||||
|
@ -287,7 +287,7 @@ RemoteUI::~RemoteUI()
|
|||
m_socket_watcher.close_fd();
|
||||
}
|
||||
|
||||
void RemoteUI::menu_show(ConstArrayView<String> choices,
|
||||
void RemoteUI::menu_show(ConstArrayView<DisplayLine> choices,
|
||||
CharCoord anchor, Face fg, Face bg,
|
||||
MenuStyle style)
|
||||
{
|
||||
|
@ -468,7 +468,7 @@ void RemoteClient::process_next_message()
|
|||
{
|
||||
case RemoteUIMsg::MenuShow:
|
||||
{
|
||||
auto choices = read_vector<String>(socket);
|
||||
auto choices = read_vector<DisplayLine>(socket);
|
||||
auto anchor = read<CharCoord>(socket);
|
||||
auto fg = read<Face>(socket);
|
||||
auto bg = read<Face>(socket);
|
||||
|
|
|
@ -41,7 +41,7 @@ class UserInterface : public SafeCountable
|
|||
public:
|
||||
virtual ~UserInterface() {}
|
||||
|
||||
virtual void menu_show(ConstArrayView<String> choices,
|
||||
virtual void menu_show(ConstArrayView<DisplayLine> choices,
|
||||
CharCoord anchor, Face fg, Face bg,
|
||||
MenuStyle style) = 0;
|
||||
virtual void menu_select(int selected) = 0;
|
||||
|
|
Loading…
Reference in New Issue
Block a user