mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-24 18:36:18 +04:00
Experiment with TUI so we can render selections.
This commit is contained in:
parent
67017e5336
commit
9ad40bc40b
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -212,6 +212,12 @@ version = "1.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cassowary"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.59"
|
version = "1.0.59"
|
||||||
@ -420,6 +426,7 @@ dependencies = [
|
|||||||
"helix-core",
|
"helix-core",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"smol",
|
"smol",
|
||||||
|
"tui",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -738,6 +745,19 @@ dependencies = [
|
|||||||
"utf-8",
|
"utf-8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tui"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a977b0bb2e2033a6fef950f218f13622c3c34e59754b704ce3492dedab1dfe95"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cassowary",
|
||||||
|
"crossterm",
|
||||||
|
"unicode-segmentation",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.6.0"
|
version = "1.6.0"
|
||||||
|
@ -22,6 +22,5 @@ crossterm = { version = "0.17.7", features = ["event-stream"] }
|
|||||||
smol = "0.4"
|
smol = "0.4"
|
||||||
futures = { version = "0.3.5", default-features = false, features = ["std", "async-await"] }
|
futures = { version = "0.3.5", default-features = false, features = ["std", "async-await"] }
|
||||||
num_cpus = "1.13.0"
|
num_cpus = "1.13.0"
|
||||||
|
tui = { version = "0.10.0", default-features = false, features = ["crossterm"] }
|
||||||
# futures-timer = "3.0.2"
|
# futures-timer = "3.0.2"
|
||||||
|
|
||||||
# tui = { version = "0.9.5", default-features = false }
|
|
||||||
|
@ -14,9 +14,17 @@
|
|||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use tui::backend::CrosstermBackend;
|
||||||
|
use tui::buffer::Buffer as Surface;
|
||||||
|
use tui::layout::Rect;
|
||||||
|
use tui::style::Style;
|
||||||
|
|
||||||
|
type Terminal = tui::Terminal<CrosstermBackend<std::io::Stdout>>;
|
||||||
|
|
||||||
static EX: smol::Executor = smol::Executor::new();
|
static EX: smol::Executor = smol::Executor::new();
|
||||||
|
|
||||||
pub struct Editor {
|
pub struct Editor {
|
||||||
|
terminal: Terminal,
|
||||||
state: Option<State>,
|
state: Option<State>,
|
||||||
first_line: u16,
|
first_line: u16,
|
||||||
size: (u16, u16),
|
size: (u16, u16),
|
||||||
@ -24,7 +32,12 @@ pub struct Editor {
|
|||||||
|
|
||||||
impl Editor {
|
impl Editor {
|
||||||
pub fn new(mut args: Args) -> Result<Self, Error> {
|
pub fn new(mut args: Args) -> Result<Self, Error> {
|
||||||
|
let backend = CrosstermBackend::new(stdout());
|
||||||
|
|
||||||
|
let mut terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
let mut editor = Editor {
|
let mut editor = Editor {
|
||||||
|
terminal,
|
||||||
state: None,
|
state: None,
|
||||||
first_line: 0,
|
first_line: 0,
|
||||||
size: terminal::size().unwrap(),
|
size: terminal::size().unwrap(),
|
||||||
@ -45,6 +58,9 @@ pub fn open(&mut self, path: PathBuf) -> Result<(), Error> {
|
|||||||
fn render(&mut self) {
|
fn render(&mut self) {
|
||||||
match &self.state {
|
match &self.state {
|
||||||
Some(state) => {
|
Some(state) => {
|
||||||
|
let area = Rect::new(0, 0, self.size.0, self.size.1);
|
||||||
|
let mut surface = Surface::empty(area);
|
||||||
|
|
||||||
let lines = state
|
let lines = state
|
||||||
.doc
|
.doc
|
||||||
.lines_at(self.first_line as usize)
|
.lines_at(self.first_line as usize)
|
||||||
@ -60,12 +76,33 @@ fn render(&mut self) {
|
|||||||
cursor::MoveTo(0, n as u16),
|
cursor::MoveTo(0, n as u16),
|
||||||
Print((n + 1).to_string())
|
Print((n + 1).to_string())
|
||||||
);
|
);
|
||||||
execute!(
|
|
||||||
stdout,
|
surface.set_string(2, n as u16, line, Style::default());
|
||||||
SetForegroundColor(Color::Reset),
|
// execute!(
|
||||||
cursor::MoveTo(2, n as u16),
|
// stdout,
|
||||||
Print(line)
|
// SetForegroundColor(Color::Reset),
|
||||||
|
// cursor::MoveTo(2, n as u16),
|
||||||
|
// Print(line)
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterate over selections and render them
|
||||||
|
let select = Style::default().bg(tui::style::Color::LightBlue);
|
||||||
|
let text = state.doc.slice(..);
|
||||||
|
for range in state.selection.ranges() {
|
||||||
|
// get terminal coords for x,y for each range pos
|
||||||
|
// TODO: this won't work with multiline
|
||||||
|
let (y1, x1) = coords_at_pos(&text, range.from());
|
||||||
|
let (y2, x2) = coords_at_pos(&text, range.to());
|
||||||
|
let area = Rect::new(
|
||||||
|
(x1 + 2) as u16,
|
||||||
|
y1 as u16,
|
||||||
|
(x2 - x1 + 1) as u16,
|
||||||
|
(y2 - y1 + 1) as u16,
|
||||||
);
|
);
|
||||||
|
surface.set_style(area, select);
|
||||||
|
|
||||||
|
// TODO: don't highlight next char in append mode
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode = match state.mode {
|
let mode = match state.mode {
|
||||||
@ -80,6 +117,13 @@ fn render(&mut self) {
|
|||||||
Print(mode)
|
Print(mode)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
use tui::backend::Backend;
|
||||||
|
// TODO: double buffer and diff here
|
||||||
|
let empty = Surface::empty(area);
|
||||||
|
self.terminal
|
||||||
|
.backend_mut()
|
||||||
|
.draw(empty.diff(&surface).into_iter());
|
||||||
|
|
||||||
// set cursor shape
|
// set cursor shape
|
||||||
match state.mode {
|
match state.mode {
|
||||||
Mode::Insert => write!(stdout, "\x1B[6 q"),
|
Mode::Insert => write!(stdout, "\x1B[6 q"),
|
||||||
|
Loading…
Reference in New Issue
Block a user