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:
Maxime Coste 2017-04-12 10:39:17 +01:00
parent 80dd9ec4cb
commit 91bfd714e4
10 changed files with 94 additions and 1 deletions

View File

@ -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;
} }

View File

@ -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

View File

@ -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
{ {

View File

@ -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);

View File

@ -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;

View File

@ -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 {}

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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;