mirror of
https://github.com/wez/wezterm.git
synced 2024-11-27 12:23:46 +03:00
termwiz: add very basic line editor
This commit is contained in:
parent
cc0d2e5493
commit
6d243ec1f1
15
termwiz/examples/line_editor.rs
Normal file
15
termwiz/examples/line_editor.rs
Normal file
@ -0,0 +1,15 @@
|
||||
use failure::Fallible;
|
||||
use termwiz::caps::Capabilities;
|
||||
use termwiz::lineedit::LineEditor;
|
||||
use termwiz::terminal::new_terminal;
|
||||
|
||||
fn main() -> Fallible<()> {
|
||||
let caps = Capabilities::new_from_env()?;
|
||||
let terminal = new_terminal(caps)?;
|
||||
let mut editor = LineEditor::new(terminal);
|
||||
|
||||
let line = editor.read_line()?;
|
||||
println!("read line: {}", line);
|
||||
|
||||
Ok(())
|
||||
}
|
@ -43,6 +43,7 @@ pub mod image;
|
||||
pub mod input;
|
||||
pub mod istty;
|
||||
pub mod keymap;
|
||||
pub mod lineedit;
|
||||
mod readbuf;
|
||||
pub mod render;
|
||||
pub mod surface;
|
||||
|
62
termwiz/src/lineedit/mod.rs
Normal file
62
termwiz/src/lineedit/mod.rs
Normal file
@ -0,0 +1,62 @@
|
||||
use crate::input::{InputEvent, KeyCode, KeyEvent, Modifiers};
|
||||
use crate::surface::{Change, Position};
|
||||
use crate::terminal::Terminal;
|
||||
use failure::Fallible;
|
||||
|
||||
pub struct LineEditor<T: Terminal> {
|
||||
terminal: T,
|
||||
line: String,
|
||||
}
|
||||
|
||||
impl<T: Terminal> LineEditor<T> {
|
||||
pub fn new(terminal: T) -> Self {
|
||||
Self {
|
||||
terminal,
|
||||
line: String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&mut self) -> Fallible<()> {
|
||||
self.terminal.render(&[
|
||||
Change::CursorPosition {
|
||||
x: Position::Absolute(0),
|
||||
y: Position::NoChange,
|
||||
},
|
||||
Change::ClearToEndOfScreen(Default::default()),
|
||||
Change::Text(self.line.clone()),
|
||||
])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read_line(&mut self) -> Fallible<String> {
|
||||
self.terminal.set_raw_mode()?;
|
||||
let res = self.read_line_impl();
|
||||
self.terminal.set_cooked_mode()?;
|
||||
println!();
|
||||
res
|
||||
}
|
||||
|
||||
fn read_line_impl(&mut self) -> Fallible<String> {
|
||||
self.line.clear();
|
||||
self.render()?;
|
||||
while let Some(event) = self.terminal.poll_input(None)? {
|
||||
match event {
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Enter,
|
||||
modifiers: Modifiers::NONE,
|
||||
}) => {
|
||||
break;
|
||||
}
|
||||
InputEvent::Key(KeyEvent {
|
||||
key: KeyCode::Char(c),
|
||||
modifiers: Modifiers::NONE,
|
||||
}) => {
|
||||
self.line.push(c);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.render()?;
|
||||
}
|
||||
Ok(self.line.clone())
|
||||
}
|
||||
}
|
@ -452,6 +452,10 @@ impl TerminfoRenderer {
|
||||
out.by_ref().write_all(b"\r\n")?;
|
||||
}
|
||||
Change::CursorPosition {
|
||||
x: Position::Absolute(0),
|
||||
y: Position::NoChange,
|
||||
}
|
||||
| Change::CursorPosition {
|
||||
x: Position::Absolute(0),
|
||||
y: Position::Relative(0),
|
||||
} => {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use crate::caps::Capabilities;
|
||||
use crate::input::InputEvent;
|
||||
use crate::surface::Change;
|
||||
use failure::{format_err, Error};
|
||||
use failure::{format_err, Error, Fallible};
|
||||
use num::{self, NumCast};
|
||||
use std::fmt::Display;
|
||||
use std::time::Duration;
|
||||
@ -56,6 +56,7 @@ pub trait Terminal {
|
||||
/// pressed by the user do not implicitly render to the terminal
|
||||
/// output, and disables canonicalization of unix newlines to CRLF.
|
||||
fn set_raw_mode(&mut self) -> Result<(), Error>;
|
||||
fn set_cooked_mode(&mut self) -> Fallible<()>;
|
||||
|
||||
/// Enter the alternate screen. The alternate screen will be left
|
||||
/// automatically when the `Terminal` is dropped.
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::istty::IsTty;
|
||||
use failure::{bail, ensure, format_err, Error};
|
||||
use failure::{bail, ensure, format_err, Error, Fallible};
|
||||
use libc::{self, poll, pollfd, winsize, POLLIN};
|
||||
use signal_hook::{self, SigId};
|
||||
use std::collections::VecDeque;
|
||||
@ -357,6 +357,11 @@ impl Terminal for UnixTerminal {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_cooked_mode(&mut self) -> Fallible<()> {
|
||||
self.write
|
||||
.set_termios(&self.saved_termios, SetAttributeWhen::Now)
|
||||
}
|
||||
|
||||
fn enter_alternate_screen(&mut self) -> Result<(), Error> {
|
||||
if !self.in_alternate_screen {
|
||||
write!(
|
||||
|
@ -521,6 +521,17 @@ impl Terminal for WindowsTerminal {
|
||||
)
|
||||
}
|
||||
|
||||
fn set_cooked_mode(&mut self) -> Fallible<()> {
|
||||
let mode = self.input_handle.get_input_mode()?;
|
||||
|
||||
self.input_handle.set_input_mode(
|
||||
(mode & !(ENABLE_WINDOW_INPUT | ENABLE_WINDOW_INPUT))
|
||||
| ENABLE_ECHO_INPUT
|
||||
| ENABLE_LINE_INPUT
|
||||
| ENABLE_PROCESSED_INPUT,
|
||||
)
|
||||
}
|
||||
|
||||
fn enter_alternate_screen(&mut self) -> Result<(), Error> {
|
||||
// TODO: Implement using CreateConsoleScreenBuffer and
|
||||
// SetConsoleActiveScreenBuffer.
|
||||
|
Loading…
Reference in New Issue
Block a user