Add cursor kind to separate hidden cursor from pos

Now IME cursor position should be correct since we can still set cursor
position without drawing the cursor.
pull/260/head
Ivan Tham 3 years ago
parent 6bdf609caa
commit 124514aa70

@ -4,7 +4,7 @@
use crossterm::event::Event; use crossterm::event::Event;
use helix_core::Position; use helix_core::Position;
use tui::{buffer::Buffer as Surface, layout::Rect}; use tui::{buffer::Buffer as Surface, layout::Rect, terminal::CursorKind};
pub type Callback = Box<dyn FnOnce(&mut Compositor)>; pub type Callback = Box<dyn FnOnce(&mut Compositor)>;
@ -47,8 +47,9 @@ pub trait Component: Any + AnyComponent {
/// Render the component onto the provided surface. /// Render the component onto the provided surface.
fn render(&self, area: Rect, frame: &mut Surface, ctx: &mut Context); fn render(&self, area: Rect, frame: &mut Surface, ctx: &mut Context);
fn cursor_position(&self, area: Rect, ctx: &Editor) -> Option<Position> { /// Get cursor position and cursor kind.
None fn cursor(&self, area: Rect, ctx: &Editor) -> (Option<Position>, CursorKind) {
(None, CursorKind::Hidden)
} }
/// May be used by the parent component to compute the child area. /// May be used by the parent component to compute the child area.
@ -137,20 +138,19 @@ impl Compositor {
layer.render(area, surface, cx) layer.render(area, surface, cx)
} }
let pos = self let (pos, kind) = self.cursor(area, cx.editor);
.cursor_position(area, cx.editor) let pos = pos.map(|pos| (pos.col as u16, pos.row as u16));
.map(|pos| (pos.col as u16, pos.row as u16));
self.terminal.draw(pos); self.terminal.draw(pos, kind);
} }
pub fn cursor_position(&self, area: Rect, editor: &Editor) -> Option<Position> { pub fn cursor(&self, area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
for layer in self.layers.iter().rev() { for layer in self.layers.iter().rev() {
if let Some(pos) = layer.cursor_position(area, editor) { if let (Some(pos), kind) = layer.cursor(area, editor) {
return Some(pos); return (Some(pos), kind);
} }
} }
None (None, CursorKind::Hidden)
} }
pub fn find(&mut self, type_name: &str) -> Option<&mut dyn Component> { pub fn find(&mut self, type_name: &str) -> Option<&mut dyn Component> {

@ -26,6 +26,7 @@ use tui::{
buffer::Buffer as Surface, buffer::Buffer as Surface,
layout::Rect, layout::Rect,
style::{Color, Modifier, Style}, style::{Color, Modifier, Style},
terminal::CursorKind,
}; };
pub struct EditorView { pub struct EditorView {
@ -739,15 +740,12 @@ impl Component for EditorView {
} }
} }
fn cursor_position(&self, area: Rect, editor: &Editor) -> Option<Position> { fn cursor(&self, area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
// match view.doc.mode() { // match view.doc.mode() {
// Mode::Insert => write!(stdout, "\x1B[6 q"), // Mode::Insert => write!(stdout, "\x1B[6 q"),
// mode => write!(stdout, "\x1B[2 q"), // mode => write!(stdout, "\x1B[2 q"),
// }; // };
// return editor.cursor_position() editor.cursor()
// It's easier to just not render the cursor and use selection rendering instead.
None
} }
} }

@ -16,6 +16,7 @@ use crate::ui::{Prompt, PromptEvent};
use helix_core::Position; use helix_core::Position;
use helix_view::editor::Action; use helix_view::editor::Action;
use helix_view::Editor; use helix_view::Editor;
use tui::terminal::CursorKind;
pub struct Picker<T> { pub struct Picker<T> {
options: Vec<T>, options: Vec<T>,
@ -304,7 +305,7 @@ impl<T: 'static> Component for Picker<T> {
} }
} }
fn cursor_position(&self, area: Rect, editor: &Editor) -> Option<Position> { fn cursor(&self, area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
// TODO: this is mostly duplicate code // TODO: this is mostly duplicate code
let area = inner_rect(area); let area = inner_rect(area);
let block = Block::default().borders(Borders::ALL); let block = Block::default().borders(Borders::ALL);
@ -314,6 +315,6 @@ impl<T: 'static> Component for Picker<T> {
// prompt area // prompt area
let area = Rect::new(inner.x + 1, inner.y, inner.width - 1, 1); let area = Rect::new(inner.x + 1, inner.y, inner.width - 1, 1);
self.prompt.cursor_position(area, editor) self.prompt.cursor(area, editor)
} }
} }

@ -116,7 +116,7 @@ impl<T: Component> Component for Popup<T> {
let position = self let position = self
.position .position
.or_else(|| cx.editor.cursor_position()) .or_else(|| cx.editor.cursor().0)
.unwrap_or_default(); .unwrap_or_default();
let (width, height) = self.size; let (width, height) = self.size;

@ -4,6 +4,7 @@ use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
use helix_core::Position; use helix_core::Position;
use helix_view::{Editor, Theme}; use helix_view::{Editor, Theme};
use std::{borrow::Cow, ops::RangeFrom}; use std::{borrow::Cow, ops::RangeFrom};
use tui::terminal::CursorKind;
pub type Completion = (RangeFrom<usize>, Cow<'static, str>); pub type Completion = (RangeFrom<usize>, Cow<'static, str>);
@ -342,11 +343,14 @@ impl Component for Prompt {
self.render_prompt(area, surface, cx) self.render_prompt(area, surface, cx)
} }
fn cursor_position(&self, area: Rect, editor: &Editor) -> Option<Position> { fn cursor(&self, area: Rect, editor: &Editor) -> (Option<Position>, CursorKind) {
let line = area.height as usize - 1; let line = area.height as usize - 1;
Some(Position::new( (
area.y as usize + line, Some(Position::new(
area.x as usize + self.prompt.len() + self.cursor, area.y as usize + line,
)) area.x as usize + self.prompt.len() + self.cursor,
)),
CursorKind::Block,
)
} }
} }

@ -8,6 +8,19 @@ enum ResizeBehavior {
Auto, Auto,
} }
#[derive(Debug)]
/// UNSTABLE
pub enum CursorKind {
/// █
Block,
/// |
// Bar,
/// _
// Underline,
/// Hidden cursor, can set cursor position with this to let IME have correct cursor position.
Hidden,
}
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
/// UNSTABLE /// UNSTABLE
pub struct Viewport { pub struct Viewport {
@ -147,7 +160,11 @@ where
/// Synchronizes terminal size, calls the rendering closure, flushes the current internal state /// Synchronizes terminal size, calls the rendering closure, flushes the current internal state
/// and prepares for the next draw call. /// and prepares for the next draw call.
pub fn draw(&mut self, cursor_position: Option<(u16, u16)>) -> io::Result<()> { pub fn draw(
&mut self,
cursor_position: Option<(u16, u16)>,
cursor_kind: CursorKind,
) -> io::Result<()> {
// // Autoresize - otherwise we get glitches if shrinking or potential desync between widgets // // Autoresize - otherwise we get glitches if shrinking or potential desync between widgets
// // and the terminal (if growing), which may OOB. // // and the terminal (if growing), which may OOB.
// self.autoresize()?; // self.autoresize()?;
@ -162,12 +179,13 @@ where
// Draw to stdout // Draw to stdout
self.flush()?; self.flush()?;
match cursor_position { if let Some((x, y)) = cursor_position {
None => self.hide_cursor()?, self.set_cursor(x, y)?;
Some((x, y)) => { }
self.show_cursor()?;
self.set_cursor(x, y)?; match cursor_kind {
} CursorKind::Block => self.show_cursor()?,
CursorKind::Hidden => self.hide_cursor()?,
} }
// Swap buffers // Swap buffers

@ -1,5 +1,6 @@
use crate::{theme::Theme, tree::Tree, Document, DocumentId, RegisterSelection, View, ViewId}; use crate::{theme::Theme, tree::Tree, Document, DocumentId, RegisterSelection, View, ViewId};
use tui::layout::Rect; use tui::layout::Rect;
use tui::terminal::CursorKind;
use std::path::PathBuf; use std::path::PathBuf;
@ -9,6 +10,7 @@ use anyhow::Error;
pub use helix_core::diagnostic::Severity; pub use helix_core::diagnostic::Severity;
pub use helix_core::register::Registers; pub use helix_core::register::Registers;
use helix_core::Position;
#[derive(Debug)] #[derive(Debug)]
pub struct Editor { pub struct Editor {
@ -276,7 +278,7 @@ impl Editor {
// let doc = &mut editor.documents[id]; // let doc = &mut editor.documents[id];
// } // }
pub fn cursor_position(&self) -> Option<helix_core::Position> { pub fn cursor(&self) -> (Option<Position>, CursorKind) {
const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
let view = self.view(); let view = self.view();
let doc = &self.documents[view.doc]; let doc = &self.documents[view.doc];
@ -284,8 +286,9 @@ impl Editor {
if let Some(mut pos) = view.screen_coords_at_pos(doc, doc.text().slice(..), cursor) { if let Some(mut pos) = view.screen_coords_at_pos(doc, doc.text().slice(..), cursor) {
pos.col += view.area.x as usize + OFFSET as usize; pos.col += view.area.x as usize + OFFSET as usize;
pos.row += view.area.y as usize; pos.row += view.area.y as usize;
return Some(pos); (Some(pos), CursorKind::Hidden)
} else {
(None, CursorKind::Hidden)
} }
None
} }
} }

Loading…
Cancel
Save