Place hardware terminal cursor at the current main cursor/prompt cursor position
Fixes #1318 Also fixes https://gitlab.com/gnachman/iterm2/issues/5408
This commit is contained in:
parent
80dd9ec4cb
commit
91bfd714e4
|
@ -246,6 +246,9 @@ void Client::redraw_ifn()
|
||||||
if (m_ui_pending & StatusLine)
|
if (m_ui_pending & StatusLine)
|
||||||
m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
|
m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
|
||||||
|
|
||||||
|
auto cursor = m_input_handler.get_cursor_info();
|
||||||
|
m_ui->set_cursor(cursor.first, cursor.second);
|
||||||
|
|
||||||
m_ui->refresh(m_ui_pending | Refresh);
|
m_ui->refresh(m_ui_pending | Refresh);
|
||||||
m_ui_pending = 0;
|
m_ui_pending = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,12 @@ public:
|
||||||
|
|
||||||
virtual KeymapMode keymap_mode() const = 0;
|
virtual KeymapMode keymap_mode() const = 0;
|
||||||
|
|
||||||
|
virtual std::pair<CursorMode, DisplayCoord> get_cursor_info() const
|
||||||
|
{
|
||||||
|
DisplayCoord coord = context().window().display_position(context().selections().main().cursor());
|
||||||
|
return {CursorMode::Buffer, coord};
|
||||||
|
}
|
||||||
|
|
||||||
using Insertion = InputHandler::Insertion;
|
using Insertion = InputHandler::Insertion;
|
||||||
Insertion& last_insert() { return m_input_handler.m_last_insert; }
|
Insertion& last_insert() { return m_input_handler.m_last_insert; }
|
||||||
|
|
||||||
|
@ -467,6 +473,11 @@ public:
|
||||||
const String& line() const { return m_line; }
|
const String& line() const { return m_line; }
|
||||||
CharCount cursor_pos() const { return m_cursor_pos; }
|
CharCount cursor_pos() const { return m_cursor_pos; }
|
||||||
|
|
||||||
|
ColumnCount cursor_display_column() const
|
||||||
|
{
|
||||||
|
return m_line.substr(m_display_pos, m_cursor_pos).column_length();
|
||||||
|
}
|
||||||
|
|
||||||
DisplayLine build_display_line(ColumnCount in_width)
|
DisplayLine build_display_line(ColumnCount in_width)
|
||||||
{
|
{
|
||||||
auto cleanup = [](StringView str) {
|
auto cleanup = [](StringView str) {
|
||||||
|
@ -873,6 +884,12 @@ public:
|
||||||
|
|
||||||
KeymapMode keymap_mode() const override { return KeymapMode::Prompt; }
|
KeymapMode keymap_mode() const override { return KeymapMode::Prompt; }
|
||||||
|
|
||||||
|
std::pair<CursorMode, DisplayCoord> get_cursor_info() const override
|
||||||
|
{
|
||||||
|
DisplayCoord coord{0_line, m_prompt.column_length() + m_line_editor.cursor_display_column()};
|
||||||
|
return { CursorMode::Prompt, coord };
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refresh_completions(CompletionFlags flags)
|
void refresh_completions(CompletionFlags flags)
|
||||||
{
|
{
|
||||||
|
@ -1521,6 +1538,11 @@ DisplayLine InputHandler::mode_line() const
|
||||||
return current_mode().mode_line();
|
return current_mode().mode_line();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<CursorMode, DisplayCoord> InputHandler::get_cursor_info() const
|
||||||
|
{
|
||||||
|
return current_mode().get_cursor_info();
|
||||||
|
}
|
||||||
|
|
||||||
bool show_auto_info_ifn(StringView title, StringView info, AutoInfo mask, const Context& context)
|
bool show_auto_info_ifn(StringView title, StringView info, AutoInfo mask, const Context& context)
|
||||||
{
|
{
|
||||||
if (not (context.options()["autoinfo"].get<AutoInfo>() & mask) or
|
if (not (context.options()["autoinfo"].get<AutoInfo>() & mask) or
|
||||||
|
|
|
@ -43,6 +43,7 @@ using KeyCallback = std::function<void (Key, Context&)>;
|
||||||
class InputMode;
|
class InputMode;
|
||||||
enum class InsertMode : unsigned;
|
enum class InsertMode : unsigned;
|
||||||
enum class KeymapMode : char;
|
enum class KeymapMode : char;
|
||||||
|
enum class CursorMode;
|
||||||
|
|
||||||
class InputHandler : public SafeCountable
|
class InputHandler : public SafeCountable
|
||||||
{
|
{
|
||||||
|
@ -91,6 +92,8 @@ public:
|
||||||
|
|
||||||
DisplayLine mode_line() const;
|
DisplayLine mode_line() const;
|
||||||
|
|
||||||
|
std::pair<CursorMode, DisplayCoord> get_cursor_info() const;
|
||||||
|
|
||||||
// Force an input handler into normal mode temporarily
|
// Force an input handler into normal mode temporarily
|
||||||
struct ScopedForceNormal
|
struct ScopedForceNormal
|
||||||
{
|
{
|
||||||
|
|
|
@ -135,6 +135,16 @@ String to_json(InfoStyle style)
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String to_json(CursorMode mode)
|
||||||
|
{
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case CursorMode::Prompt: return R"("prompt")";
|
||||||
|
case CursorMode::Buffer: return R"("buffer")";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
String concat()
|
String concat()
|
||||||
{
|
{
|
||||||
return "";
|
return "";
|
||||||
|
@ -209,6 +219,11 @@ void JsonUI::info_hide()
|
||||||
rpc_call("info_hide");
|
rpc_call("info_hide");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void JsonUI::set_cursor(CursorMode mode, DisplayCoord coord)
|
||||||
|
{
|
||||||
|
rpc_call("set_cursor", mode, coord);
|
||||||
|
}
|
||||||
|
|
||||||
void JsonUI::refresh(bool force)
|
void JsonUI::refresh(bool force)
|
||||||
{
|
{
|
||||||
rpc_call("refresh", force);
|
rpc_call("refresh", force);
|
||||||
|
|
|
@ -38,6 +38,8 @@ public:
|
||||||
InfoStyle style) override;
|
InfoStyle style) override;
|
||||||
void info_hide() override;
|
void info_hide() override;
|
||||||
|
|
||||||
|
void set_cursor(CursorMode mode, DisplayCoord coord) override;
|
||||||
|
|
||||||
void refresh(bool force) override;
|
void refresh(bool force) override;
|
||||||
|
|
||||||
DisplayCoord dimensions() override;
|
DisplayCoord dimensions() override;
|
||||||
|
|
|
@ -356,6 +356,7 @@ std::unique_ptr<UserInterface> make_ui(UIType ui_type)
|
||||||
void draw(const DisplayBuffer&, const Face&, const Face&) override {}
|
void draw(const DisplayBuffer&, const Face&, const Face&) override {}
|
||||||
void draw_status(const DisplayLine&, const DisplayLine&, const Face&) override {}
|
void draw_status(const DisplayLine&, const DisplayLine&, const Face&) override {}
|
||||||
DisplayCoord dimensions() override { return {24,80}; }
|
DisplayCoord dimensions() override { return {24,80}; }
|
||||||
|
void set_cursor(CursorMode, DisplayCoord) override {}
|
||||||
void refresh(bool) override {}
|
void refresh(bool) override {}
|
||||||
void set_on_key(OnKeyCallback) override {}
|
void set_on_key(OnKeyCallback) override {}
|
||||||
void set_ui_options(const Options&) override {}
|
void set_ui_options(const Options&) override {}
|
||||||
|
|
|
@ -312,11 +312,25 @@ void NCursesUI::redraw()
|
||||||
{
|
{
|
||||||
pnoutrefresh(m_window, 0, 0, 0, 0,
|
pnoutrefresh(m_window, 0, 0, 0, 0,
|
||||||
(int)m_dimensions.line + 1, (int)m_dimensions.column);
|
(int)m_dimensions.line + 1, (int)m_dimensions.column);
|
||||||
|
|
||||||
m_menu.refresh();
|
m_menu.refresh();
|
||||||
m_info.refresh();
|
m_info.refresh();
|
||||||
|
|
||||||
|
if (m_cursor.mode == CursorMode::Prompt)
|
||||||
|
wmove(newscr, m_status_on_top ? 0 : (int)m_dimensions.line + 1,
|
||||||
|
(int)m_cursor.coord.column);
|
||||||
|
else
|
||||||
|
wmove(newscr, (int)m_cursor.coord.line + (m_status_on_top ? 1 : 0),
|
||||||
|
(int)m_cursor.coord.column);
|
||||||
|
|
||||||
doupdate();
|
doupdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NCursesUI::set_cursor(CursorMode mode, DisplayCoord coord)
|
||||||
|
{
|
||||||
|
m_cursor = Cursor{ mode, coord };
|
||||||
|
}
|
||||||
|
|
||||||
void NCursesUI::refresh(bool force)
|
void NCursesUI::refresh(bool force)
|
||||||
{
|
{
|
||||||
if (force)
|
if (force)
|
||||||
|
|
|
@ -43,8 +43,9 @@ public:
|
||||||
InfoStyle style) override;
|
InfoStyle style) override;
|
||||||
void info_hide() override;
|
void info_hide() override;
|
||||||
|
|
||||||
void refresh(bool force) override;
|
void set_cursor(CursorMode mode, DisplayCoord coord) override;
|
||||||
|
|
||||||
|
void refresh(bool force) override;
|
||||||
|
|
||||||
DisplayCoord dimensions() override;
|
DisplayCoord dimensions() override;
|
||||||
void set_on_key(OnKeyCallback callback) override;
|
void set_on_key(OnKeyCallback callback) override;
|
||||||
|
@ -121,6 +122,12 @@ private:
|
||||||
InfoStyle style;
|
InfoStyle style;
|
||||||
} m_info;
|
} m_info;
|
||||||
|
|
||||||
|
struct Cursor
|
||||||
|
{
|
||||||
|
CursorMode mode;
|
||||||
|
DisplayCoord coord;
|
||||||
|
} m_cursor;
|
||||||
|
|
||||||
FDWatcher m_stdin_watcher;
|
FDWatcher m_stdin_watcher;
|
||||||
OnKeyCallback m_on_key;
|
OnKeyCallback m_on_key;
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ enum class MessageType : char
|
||||||
InfoHide,
|
InfoHide,
|
||||||
Draw,
|
Draw,
|
||||||
DrawStatus,
|
DrawStatus,
|
||||||
|
SetCursor,
|
||||||
Refresh,
|
Refresh,
|
||||||
SetOptions,
|
SetOptions,
|
||||||
Key
|
Key
|
||||||
|
@ -335,6 +336,8 @@ public:
|
||||||
const DisplayLine& mode_line,
|
const DisplayLine& mode_line,
|
||||||
const Face& default_face) override;
|
const Face& default_face) override;
|
||||||
|
|
||||||
|
void set_cursor(CursorMode mode, DisplayCoord coord) override;
|
||||||
|
|
||||||
void refresh(bool force) override;
|
void refresh(bool force) override;
|
||||||
|
|
||||||
DisplayCoord dimensions() override { return m_dimensions; }
|
DisplayCoord dimensions() override { return m_dimensions; }
|
||||||
|
@ -483,6 +486,14 @@ void RemoteUI::draw_status(const DisplayLine& status_line,
|
||||||
m_socket_watcher.events() |= FdEvents::Write;
|
m_socket_watcher.events() |= FdEvents::Write;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteUI::set_cursor(CursorMode mode, DisplayCoord coord)
|
||||||
|
{
|
||||||
|
MsgWriter msg{m_send_buffer, MessageType::SetCursor};
|
||||||
|
msg.write(mode);
|
||||||
|
msg.write(coord);
|
||||||
|
m_socket_watcher.events() |= FdEvents::Write;
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteUI::refresh(bool force)
|
void RemoteUI::refresh(bool force)
|
||||||
{
|
{
|
||||||
MsgWriter msg{m_send_buffer, MessageType::Refresh};
|
MsgWriter msg{m_send_buffer, MessageType::Refresh};
|
||||||
|
@ -611,6 +622,13 @@ RemoteClient::RemoteClient(StringView session, std::unique_ptr<UserInterface>&&
|
||||||
m_ui->draw_status(status_line, mode_line, default_face);
|
m_ui->draw_status(status_line, mode_line, default_face);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case MessageType::SetCursor:
|
||||||
|
{
|
||||||
|
auto mode = reader.read<CursorMode>();
|
||||||
|
auto coord = reader.read<DisplayCoord>();
|
||||||
|
m_ui->set_cursor(mode, coord);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case MessageType::Refresh:
|
case MessageType::Refresh:
|
||||||
m_ui->refresh(reader.read<bool>());
|
m_ui->refresh(reader.read<bool>());
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -34,6 +34,12 @@ enum class InfoStyle
|
||||||
|
|
||||||
enum class EventMode;
|
enum class EventMode;
|
||||||
|
|
||||||
|
enum class CursorMode
|
||||||
|
{
|
||||||
|
Prompt,
|
||||||
|
Buffer,
|
||||||
|
};
|
||||||
|
|
||||||
using OnKeyCallback = std::function<void(Key key)>;
|
using OnKeyCallback = std::function<void(Key key)>;
|
||||||
|
|
||||||
class UserInterface
|
class UserInterface
|
||||||
|
@ -62,6 +68,8 @@ public:
|
||||||
|
|
||||||
virtual DisplayCoord dimensions() = 0;
|
virtual DisplayCoord dimensions() = 0;
|
||||||
|
|
||||||
|
virtual void set_cursor(CursorMode mode, DisplayCoord coord) = 0;
|
||||||
|
|
||||||
virtual void refresh(bool force) = 0;
|
virtual void refresh(bool force) = 0;
|
||||||
|
|
||||||
virtual void set_on_key(OnKeyCallback callback) = 0;
|
virtual void set_on_key(OnKeyCallback callback) = 0;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user