Add MenuStyle::Search that prevents the menu from hiding buffer text
Fixes #2042
This commit is contained in:
parent
56e5322b45
commit
2bdbf7e379
|
@ -954,7 +954,9 @@ private:
|
||||||
Vector<DisplayLine> items;
|
Vector<DisplayLine> items;
|
||||||
for (auto& candidate : m_completions.candidates)
|
for (auto& candidate : m_completions.candidates)
|
||||||
items.push_back({ candidate, {} });
|
items.push_back({ candidate, {} });
|
||||||
context().client().menu_show(items, {}, MenuStyle::Prompt);
|
|
||||||
|
const auto menu_style = (m_flags & PromptFlags::Search) ? MenuStyle::Search : MenuStyle::Prompt;
|
||||||
|
context().client().menu_show(items, {}, menu_style);
|
||||||
|
|
||||||
auto prefix = line.substr(m_completions.start, m_completions.end - m_completions.start);
|
auto prefix = line.substr(m_completions.start, m_completions.end - m_completions.start);
|
||||||
if (not contains(m_completions.candidates, prefix))
|
if (not contains(m_completions.candidates, prefix))
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum class PromptFlags
|
||||||
None = 0,
|
None = 0,
|
||||||
Password = 1 << 0,
|
Password = 1 << 0,
|
||||||
DropHistoryEntriesWithBlankPrefix = 1 << 1,
|
DropHistoryEntriesWithBlankPrefix = 1 << 1,
|
||||||
|
Search = 1 << 2,
|
||||||
};
|
};
|
||||||
constexpr bool with_bit_ops(Meta::Type<PromptFlags>) { return true; }
|
constexpr bool with_bit_ops(Meta::Type<PromptFlags>) { return true; }
|
||||||
|
|
||||||
|
|
|
@ -117,6 +117,7 @@ String to_json(MenuStyle style)
|
||||||
switch (style)
|
switch (style)
|
||||||
{
|
{
|
||||||
case MenuStyle::Prompt: return R"("prompt")";
|
case MenuStyle::Prompt: return R"("prompt")";
|
||||||
|
case MenuStyle::Search: return R"("search")";
|
||||||
case MenuStyle::Inline: return R"("inline")";
|
case MenuStyle::Inline: return R"("inline")";
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
|
|
|
@ -228,6 +228,12 @@ static void signal_handler(int)
|
||||||
EventManager::instance().force_signal(0);
|
EventManager::instance().force_signal(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_ungetch(int ch)
|
||||||
|
{
|
||||||
|
ungetch(ch);
|
||||||
|
EventManager::instance().force_signal(0);
|
||||||
|
}
|
||||||
|
|
||||||
static const std::initializer_list<HashMap<Kakoune::Color, int>::Item>
|
static const std::initializer_list<HashMap<Kakoune::Color, int>::Item>
|
||||||
default_colors = {
|
default_colors = {
|
||||||
{ Color::Default, -1 },
|
{ Color::Default, -1 },
|
||||||
|
@ -331,7 +337,7 @@ void NCursesUI::redraw()
|
||||||
wmove(newscr, m_status_on_top ? 0 : (int)m_dimensions.line,
|
wmove(newscr, m_status_on_top ? 0 : (int)m_dimensions.line,
|
||||||
(int)m_cursor.coord.column);
|
(int)m_cursor.coord.column);
|
||||||
else
|
else
|
||||||
wmove(newscr, (int)m_cursor.coord.line + (m_status_on_top ? 1 : 0),
|
wmove(newscr, (int)(m_cursor.coord.line + content_line_offset()),
|
||||||
(int)m_cursor.coord.column);
|
(int)m_cursor.coord.column);
|
||||||
|
|
||||||
doupdate();
|
doupdate();
|
||||||
|
@ -395,7 +401,8 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer,
|
||||||
|
|
||||||
check_resize();
|
check_resize();
|
||||||
|
|
||||||
LineCount line_index = m_status_on_top ? 1 : 0;
|
const LineCount line_offset = content_line_offset();
|
||||||
|
LineCount line_index = line_offset;
|
||||||
for (const DisplayLine& line : display_buffer.lines())
|
for (const DisplayLine& line : display_buffer.lines())
|
||||||
{
|
{
|
||||||
wmove(m_window, (int)line_index, 0);
|
wmove(m_window, (int)line_index, 0);
|
||||||
|
@ -407,7 +414,7 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer,
|
||||||
wbkgdset(m_window, COLOR_PAIR(get_color_pair(padding_face)));
|
wbkgdset(m_window, COLOR_PAIR(get_color_pair(padding_face)));
|
||||||
set_face(m_window, padding_face, default_face);
|
set_face(m_window, padding_face, default_face);
|
||||||
|
|
||||||
while (line_index < m_dimensions.line + (m_status_on_top ? 1 : 0))
|
while (line_index < m_dimensions.line + line_offset)
|
||||||
{
|
{
|
||||||
wmove(m_window, (int)line_index++, 0);
|
wmove(m_window, (int)line_index++, 0);
|
||||||
wclrtoeol(m_window);
|
wclrtoeol(m_window);
|
||||||
|
@ -514,7 +521,7 @@ void NCursesUI::check_resize(bool force)
|
||||||
if (info)
|
if (info)
|
||||||
info_show(m_info.title, m_info.content, m_info.anchor, m_info.face, m_info.style);
|
info_show(m_info.title, m_info.content, m_info.anchor, m_info.face, m_info.style);
|
||||||
|
|
||||||
ungetch(KEY_RESIZE);
|
do_ungetch(KEY_RESIZE);
|
||||||
clearok(curscr, true);
|
clearok(curscr, true);
|
||||||
werase(curscr);
|
werase(curscr);
|
||||||
}
|
}
|
||||||
|
@ -560,7 +567,7 @@ Optional<Key> NCursesUI::get_next_key()
|
||||||
};
|
};
|
||||||
|
|
||||||
return Key{ get_modifiers(ev.bstate),
|
return Key{ get_modifiers(ev.bstate),
|
||||||
encode_coord({ ev.y - (m_status_on_top ? 1 : 0), ev.x }) };
|
encode_coord({ ev.y - content_line_offset(), ev.x }) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +597,7 @@ Optional<Key> NCursesUI::get_next_key()
|
||||||
case KEY_END: return {Key::End};
|
case KEY_END: return {Key::End};
|
||||||
case KEY_SEND: return shift(Key::End);
|
case KEY_SEND: return shift(Key::End);
|
||||||
case KEY_BTAB: return shift(Key::Tab);
|
case KEY_BTAB: return shift(Key::Tab);
|
||||||
case KEY_RESIZE: return resize(m_dimensions);
|
case KEY_RESIZE: return resize(dimensions());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c > 0 and c < 27)
|
if (c > 0 and c < 27)
|
||||||
|
@ -724,7 +731,13 @@ void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
|
||||||
DisplayCoord anchor, Face fg, Face bg,
|
DisplayCoord anchor, Face fg, Face bg,
|
||||||
MenuStyle style)
|
MenuStyle style)
|
||||||
{
|
{
|
||||||
menu_hide();
|
const LineCount previous_height = m_menu ? m_menu.size.line : 0;
|
||||||
|
if (m_menu)
|
||||||
|
{
|
||||||
|
mark_dirty(m_menu);
|
||||||
|
m_menu.destroy();
|
||||||
|
m_dirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
m_menu.fg = fg;
|
m_menu.fg = fg;
|
||||||
m_menu.bg = bg;
|
m_menu.bg = bg;
|
||||||
|
@ -758,8 +771,8 @@ void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
|
||||||
kak_assert(m_menu.items.back().length() <= maxlen);
|
kak_assert(m_menu.items.back().length() <= maxlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_inline and m_status_on_top)
|
if (is_inline)
|
||||||
anchor.line += 1;
|
anchor.line += content_line_offset();
|
||||||
|
|
||||||
LineCount line = anchor.line + 1;
|
LineCount line = anchor.line + 1;
|
||||||
if (not is_inline)
|
if (not is_inline)
|
||||||
|
@ -774,6 +787,9 @@ void NCursesUI::menu_show(ConstArrayView<DisplayLine> items,
|
||||||
m_menu.selected_item = item_count;
|
m_menu.selected_item = item_count;
|
||||||
m_menu.first_item = 0;
|
m_menu.first_item = 0;
|
||||||
|
|
||||||
|
if (style == MenuStyle::Search and previous_height != height)
|
||||||
|
do_ungetch(KEY_RESIZE);
|
||||||
|
|
||||||
draw_menu();
|
draw_menu();
|
||||||
|
|
||||||
if (m_info)
|
if (m_info)
|
||||||
|
@ -809,6 +825,10 @@ void NCursesUI::menu_hide()
|
||||||
{
|
{
|
||||||
if (not m_menu)
|
if (not m_menu)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (m_menu.style == MenuStyle::Search)
|
||||||
|
do_ungetch(KEY_RESIZE);
|
||||||
|
|
||||||
m_menu.items.clear();
|
m_menu.items.clear();
|
||||||
mark_dirty(m_menu);
|
mark_dirty(m_menu);
|
||||||
m_menu.destroy();
|
m_menu.destroy();
|
||||||
|
@ -948,7 +968,7 @@ void NCursesUI::info_show(StringView title, StringView content,
|
||||||
m_info.face = face;
|
m_info.face = face;
|
||||||
m_info.style = style;
|
m_info.style = style;
|
||||||
|
|
||||||
const Rect rect = {m_status_on_top ? 1_line : 0_line, m_dimensions};
|
const Rect rect = {content_line_offset(), m_dimensions};
|
||||||
InfoBox info_box;
|
InfoBox info_box;
|
||||||
if (style == InfoStyle::Prompt)
|
if (style == InfoStyle::Prompt)
|
||||||
{
|
{
|
||||||
|
@ -989,8 +1009,7 @@ void NCursesUI::info_show(StringView title, StringView content,
|
||||||
info_box = make_simple_info_box(m_info.content, max_width);
|
info_box = make_simple_info_box(m_info.content, max_width);
|
||||||
anchor = compute_pos(anchor, info_box.size, rect, m_menu, style == InfoStyle::InlineAbove);
|
anchor = compute_pos(anchor, info_box.size, rect, m_menu, style == InfoStyle::InlineAbove);
|
||||||
|
|
||||||
if (m_status_on_top)
|
anchor.line += content_line_offset();
|
||||||
anchor.line += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The info box does not fit
|
// The info box does not fit
|
||||||
|
@ -1025,11 +1044,20 @@ void NCursesUI::mark_dirty(const Window& win)
|
||||||
void NCursesUI::set_on_key(OnKeyCallback callback)
|
void NCursesUI::set_on_key(OnKeyCallback callback)
|
||||||
{
|
{
|
||||||
m_on_key = std::move(callback);
|
m_on_key = std::move(callback);
|
||||||
|
EventManager::instance().force_signal(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DisplayCoord NCursesUI::dimensions()
|
DisplayCoord NCursesUI::dimensions()
|
||||||
{
|
{
|
||||||
return m_dimensions;
|
auto res = m_dimensions;
|
||||||
|
if (m_menu and m_menu.style == MenuStyle::Search)
|
||||||
|
res.line -= m_menu.size.line;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
LineCount NCursesUI::content_line_offset() const
|
||||||
|
{
|
||||||
|
return (m_status_on_top ? 1 + (m_menu.style == MenuStyle::Search ? m_menu.size.line : 0) : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NCursesUI::abort()
|
void NCursesUI::abort()
|
||||||
|
|
|
@ -106,12 +106,14 @@ private:
|
||||||
DisplayCoord anchor;
|
DisplayCoord anchor;
|
||||||
MenuStyle style;
|
MenuStyle style;
|
||||||
int selected_item = 0;
|
int selected_item = 0;
|
||||||
|
int first_item = 0;
|
||||||
int columns = 1;
|
int columns = 1;
|
||||||
LineCount top_line = 0;
|
|
||||||
} m_menu;
|
} m_menu;
|
||||||
|
|
||||||
void draw_menu();
|
void draw_menu();
|
||||||
|
|
||||||
|
LineCount content_line_offset() const;
|
||||||
|
|
||||||
struct Info : Window
|
struct Info : Window
|
||||||
{
|
{
|
||||||
String title;
|
String title;
|
||||||
|
|
|
@ -736,7 +736,7 @@ void regex_prompt(Context& context, String prompt, String default_regex, T func)
|
||||||
SelectionList selections = context.selections();
|
SelectionList selections = context.selections();
|
||||||
context.input_handler().prompt(
|
context.input_handler().prompt(
|
||||||
std::move(prompt), {}, default_regex, context.faces()["Prompt"],
|
std::move(prompt), {}, default_regex, context.faces()["Prompt"],
|
||||||
PromptFlags::None,
|
PromptFlags::Search,
|
||||||
[](const Context& context, CompletionFlags, StringView regex, ByteCount pos) -> Completions {
|
[](const Context& context, CompletionFlags, StringView regex, ByteCount pos) -> Completions {
|
||||||
auto current_word = [](StringView s) {
|
auto current_word = [](StringView s) {
|
||||||
auto it = s.end();
|
auto it = s.end();
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct Key;
|
||||||
enum class MenuStyle
|
enum class MenuStyle
|
||||||
{
|
{
|
||||||
Prompt,
|
Prompt,
|
||||||
|
Search,
|
||||||
Inline
|
Inline
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user