rhysd / tui-textarea

Simple yet powerful multi-line text editor widget for ratatui and tui-rs
https://crates.io/crates/tui-textarea
MIT License
341 stars 63 forks source link

Change cursor shape #11

Closed brooksvb closed 1 year ago

brooksvb commented 1 year ago

I've been trying to change the cursor style to a blinking bar for an editor program, but it seems like there isn't a way to do this beyond changing cursor color and blink rate.

I've tried doing so through crossterm but it seems like this is ignored in the rendering of the textarea.

//main.rs
...
use crossterm::cursor::SetCursorStyle;
use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
use crossterm::terminal::{
    disable_raw_mode, enable_raw_mode, is_raw_mode_enabled, EnterAlternateScreen,
    LeaveAlternateScreen,
};
...
    crossterm::execute!(term.backend_mut(), SetCursorStyle::SteadyBar).unwrap();

    // Main render loop
    let mutex = Mutex::new(());
    while running.load(Ordering::SeqCst) {
        term.draw(|f| {
            let buffer = buffer.lock().unwrap();
            let buffer_widget = buffer.textarea.widget();
            let rectangle = Rect::new(0, 0, f.size().width, f.size().height);
            f.render_widget(buffer_widget, rectangle);
        })
        .unwrap();

        // TUI refresh rate
        let guard = mutex.lock().unwrap();
        _ = condvar.wait_timeout(guard, Duration::from_millis(50));
    }
...

And my implementation of Buffer which creates the TextArea

...
impl Buffer {
    pub fn new(config: &Config) -> io::Result<Self> {
        // TODO: Generate path
        let path = config.output_name.clone();

        let file_already_existed = path.exists();
        let mut textarea = if let Ok(md) = path.metadata() {
            if md.is_file() {
                let contents = fs::read_to_string(path.clone())?;
                TextArea::from(contents.lines())
            } else {
                // Path exists but is not a file
                return Err(io::Error::new(
                    io::ErrorKind::Other,
                    format!("{:?} exists but is not a file", path),
                ));
            }
        } else {
            TextArea::default() // File does not exist
        };
        textarea.set_hard_tab_indent(config.use_hard_indent);
        // Remove default underline style from active line
        textarea.set_cursor_line_style(Style::default());
        Ok(Self {
            textarea,
            path,
            modified: false,
            file_already_existed,
        })
    }
    ...

I've tried calling textarea.set_cursor_style from here (https://docs.rs/tui-textarea/latest/tui_textarea/struct.TextArea.html#method.set_cursor_style), but the Style struct from the tui crate just doesn't seem to support a way to change the cursor shape.

Is this a limitation of the tui crate? Is there a way I can change my cursor shape?

rhysd commented 1 year ago

Looks duplicate of #7. Do you have any points to discuss which are not done in #7?

brooksvb commented 1 year ago

It is a duplicate. My apologies for not seeing the issue.

If I understand correctly, the cursor shown in a textarea is sort of a "virtual cursor," and not controlled/rendered by the terminal, which is why my crossterm method did not work.