Compare commits

...

3 Commits

Author SHA1 Message Date
nyx
85e533fb20
Merge 9a18d08dd3 into fa69885b6c 2024-11-17 02:39:46 +01:00
Jeevitha Kannan K S
fa69885b6c
Use vt100-ctt instead of patching the dep (#952)
Thanks @a-kenji
2024-11-16 15:07:22 -06:00
nyx
9a18d08dd3
Revert "feat: Mouse scroll (#913)"
This reverts commit 432d6b3b0c.
2024-11-12 06:22:48 -05:00
9 changed files with 24 additions and 143 deletions

8
Cargo.lock generated
View File

@ -425,6 +425,7 @@ dependencies = [
"tree-sitter-highlight", "tree-sitter-highlight",
"tui-term", "tui-term",
"unicode-width 0.2.0", "unicode-width 0.2.0",
"vt100-ctt",
"zips", "zips",
] ]
@ -1096,7 +1097,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72af159125ce32b02ceaced6cffae6394b0e6b6dfd4dc164a6c59a2db9b3c0b0" checksum = "72af159125ce32b02ceaced6cffae6394b0e6b6dfd4dc164a6c59a2db9b3c0b0"
dependencies = [ dependencies = [
"ratatui", "ratatui",
"vt100",
] ]
[[package]] [[package]]
@ -1147,9 +1147,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "vt100" name = "vt100-ctt"
version = "0.15.2" version = "0.15.3"
source = "git+https://github.com/ChrisTitusTech/vt100-rust#e41fb3d8fb5fd01dd2d076c9a25823a31656012f" source = "git+https://github.com/ChrisTitusTech/vt100-rust#39136a6232d043d8447afa7d47805b6f6baa09ee"
dependencies = [ dependencies = [
"itoa", "itoa",
"log", "log",

View File

@ -8,9 +8,6 @@ members = ["tui", "core", "xtask"]
default-members = ["tui", "core"] default-members = ["tui", "core"]
resolver = "2" resolver = "2"
[patch.crates-io]
vt100 = { git = "https://github.com/ChrisTitusTech/vt100-rust" }
[profile.release] [profile.release]
opt-level = "z" opt-level = "z"
debug = false debug = false

View File

@ -18,7 +18,7 @@ clap = { version = "4.5.20", features = ["derive", "std"], default-features = fa
oneshot = { version = "0.1.8", features = ["std"], default-features = false } oneshot = { version = "0.1.8", features = ["std"], default-features = false }
portable-pty = "0.8.1" portable-pty = "0.8.1"
ratatui = { version = "0.29.0", features = ["crossterm"], default-features = false } ratatui = { version = "0.29.0", features = ["crossterm"], default-features = false }
tui-term = "0.2.0" tui-term = { version = "0.2.0", default-features = false }
temp-dir = "0.1.14" temp-dir = "0.1.14"
time = { version = "0.3.36", features = ["formatting", "local-offset", "macros"], default-features = false } time = { version = "0.3.36", features = ["formatting", "local-offset", "macros"], default-features = false }
unicode-width = { version = "0.2.0", default-features = false } unicode-width = { version = "0.2.0", default-features = false }
@ -31,6 +31,7 @@ anstyle = { version = "1.0.8", default-features = false }
ansi-to-tui = { version = "7.0.0", default-features = false } ansi-to-tui = { version = "7.0.0", default-features = false }
zips = "0.1.7" zips = "0.1.7"
nix = { version = "0.29.0", features = [ "user" ] } nix = { version = "0.29.0", features = [ "user" ] }
vt100-ctt = { git = "https://github.com/ChrisTitusTech/vt100-rust" }
[[bin]] [[bin]]
name = "linutil" name = "linutil"

View File

@ -3,7 +3,7 @@ use std::borrow::Cow;
use crate::{float::FloatContent, hint::Shortcut}; use crate::{float::FloatContent, hint::Shortcut};
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent},
layout::Alignment, layout::Alignment,
prelude::*, prelude::*,
widgets::{Block, Borders, Clear, List}, widgets::{Block, Borders, Clear, List},
@ -85,19 +85,6 @@ impl FloatContent for ConfirmPrompt {
frame.render_widget(List::new(paths_text), inner_area); frame.render_widget(List::new(paths_text), inner_area);
} }
fn handle_mouse_event(&mut self, event: &MouseEvent) -> bool {
match event.kind {
MouseEventKind::ScrollDown => {
self.scroll_down();
}
MouseEventKind::ScrollUp => {
self.scroll_up();
}
_ => {}
}
false
}
fn handle_key_event(&mut self, key: &KeyEvent) -> bool { fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
use KeyCode::*; use KeyCode::*;
self.status = match key.code { self.status = match key.code {

View File

@ -1,5 +1,5 @@
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent}, crossterm::event::{KeyCode, KeyEvent},
layout::{Constraint, Direction, Layout, Rect}, layout::{Constraint, Direction, Layout, Rect},
Frame, Frame,
}; };
@ -9,7 +9,6 @@ use crate::hint::Shortcut;
pub trait FloatContent { pub trait FloatContent {
fn draw(&mut self, frame: &mut Frame, area: Rect); fn draw(&mut self, frame: &mut Frame, area: Rect);
fn handle_key_event(&mut self, key: &KeyEvent) -> bool; fn handle_key_event(&mut self, key: &KeyEvent) -> bool;
fn handle_mouse_event(&mut self, key: &MouseEvent) -> bool;
fn is_finished(&self) -> bool; fn is_finished(&self) -> bool;
fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>); fn get_shortcut_list(&self) -> (&str, Box<[Shortcut]>);
} }
@ -54,10 +53,6 @@ impl<Content: FloatContent + ?Sized> Float<Content> {
self.content.draw(frame, popup_area); self.content.draw(frame, popup_area);
} }
pub fn handle_mouse_event(&mut self, event: &MouseEvent) {
self.content.handle_mouse_event(event);
}
// Returns true if the floating window is finished. // Returns true if the floating window is finished.
pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool { pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
match key.code { match key.code {

View File

@ -9,7 +9,7 @@ use crate::{float::FloatContent, hint::Shortcut};
use linutil_core::Command; use linutil_core::Command;
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent},
layout::Rect, layout::Rect,
style::{Style, Stylize}, style::{Style, Stylize},
text::Line, text::Line,
@ -283,17 +283,6 @@ impl FloatContent for FloatingText {
frame.render_widget(list, inner_area); frame.render_widget(list, inner_area);
} }
fn handle_mouse_event(&mut self, event: &MouseEvent) -> bool {
match event.kind {
MouseEventKind::ScrollDown => self.scroll_down(),
MouseEventKind::ScrollUp => self.scroll_up(),
MouseEventKind::ScrollLeft => self.scroll_left(),
MouseEventKind::ScrollRight => self.scroll_right(),
_ => {}
}
false
}
fn handle_key_event(&mut self, key: &KeyEvent) -> bool { fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
use KeyCode::*; use KeyCode::*;
match key.code { match key.code {

View File

@ -20,7 +20,7 @@ use clap::Parser;
use ratatui::{ use ratatui::{
backend::CrosstermBackend, backend::CrosstermBackend,
crossterm::{ crossterm::{
event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyEventKind}, event::{self, DisableMouseCapture, Event, KeyEventKind},
style::ResetColor, style::ResetColor,
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
ExecutableCommand, ExecutableCommand,
@ -64,8 +64,6 @@ fn main() -> io::Result<()> {
); );
stdout().execute(EnterAlternateScreen)?; stdout().execute(EnterAlternateScreen)?;
stdout().execute(EnableMouseCapture)?;
enable_raw_mode()?; enable_raw_mode()?;
let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?; let mut terminal = Terminal::new(CrosstermBackend::new(stdout()))?;
terminal.clear()?; terminal.clear()?;
@ -95,22 +93,15 @@ fn run(
// It's guaranteed that the `read()` won't block when the `poll()` // It's guaranteed that the `read()` won't block when the `poll()`
// function returns `true` // function returns `true`
match event::read()? { if let Event::Key(key) = event::read()? {
Event::Key(key) => { // We are only interested in Press and Repeat events
if key.kind != KeyEventKind::Press && key.kind != KeyEventKind::Repeat { if key.kind != KeyEventKind::Press && key.kind != KeyEventKind::Repeat {
continue; continue;
} }
if !state.handle_key(&key) { if !state.handle_key(&key) {
return Ok(()); return Ok(());
}
} }
Event::Mouse(mouse_event) => {
if !state.handle_mouse(&mouse_event) {
return Ok(());
}
}
_ => {}
} }
} }
} }

View File

@ -5,7 +5,7 @@ use portable_pty::{
ChildKiller, CommandBuilder, ExitStatus, MasterPty, NativePtySystem, PtySize, PtySystem, ChildKiller, CommandBuilder, ExitStatus, MasterPty, NativePtySystem, PtySize, PtySystem,
}; };
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, KeyModifiers, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
layout::{Rect, Size}, layout::{Rect, Size},
style::{Color, Style, Stylize}, style::{Color, Style, Stylize},
text::{Line, Span}, text::{Line, Span},
@ -18,10 +18,9 @@ use std::{
thread::JoinHandle, thread::JoinHandle,
}; };
use time::{macros::format_description, OffsetDateTime}; use time::{macros::format_description, OffsetDateTime};
use tui_term::{ use tui_term::widget::PseudoTerminal;
vt100::{self, Screen}, use vt100_ctt::{Parser, Screen};
widget::PseudoTerminal,
};
pub struct RunningCommand { pub struct RunningCommand {
/// A buffer to save all the command output (accumulates, until the command exits) /// A buffer to save all the command output (accumulates, until the command exits)
buffer: Arc<Mutex<Vec<u8>>>, buffer: Arc<Mutex<Vec<u8>>>,
@ -104,18 +103,6 @@ impl FloatContent for RunningCommand {
frame.render_widget(pseudo_term, area); frame.render_widget(pseudo_term, area);
} }
fn handle_mouse_event(&mut self, event: &MouseEvent) -> bool {
match event.kind {
MouseEventKind::ScrollUp => {
self.scroll_offset = self.scroll_offset.saturating_add(1);
}
MouseEventKind::ScrollDown => {
self.scroll_offset = self.scroll_offset.saturating_sub(1);
}
_ => {}
}
true
}
/// Handle key events of the running command "window". Returns true when the "window" should be /// Handle key events of the running command "window". Returns true when the "window" should be
/// closed /// closed
fn handle_key_event(&mut self, key: &KeyEvent) -> bool { fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
@ -285,7 +272,7 @@ impl RunningCommand {
// Process the buffer with a parser with the current screen size // Process the buffer with a parser with the current screen size
// We don't actually need to create a new parser every time, but it is so much easier this // We don't actually need to create a new parser every time, but it is so much easier this
// way, and doesn't cost that much // way, and doesn't cost that much
let mut parser = vt100::Parser::new(size.height, size.width, 1000); let mut parser = Parser::new(size.height, size.width, 1000);
let mutex = self.buffer.lock(); let mutex = self.buffer.lock();
let buffer = mutex.as_ref().unwrap(); let buffer = mutex.as_ref().unwrap();
parser.process(buffer); parser.process(buffer);

View File

@ -13,8 +13,8 @@ use linutil_core::{ego_tree::NodeId, Config, ListNode, TabList};
#[cfg(feature = "tips")] #[cfg(feature = "tips")]
use rand::Rng; use rand::Rng;
use ratatui::{ use ratatui::{
crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers, MouseEvent, MouseEventKind}, crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers},
layout::{Alignment, Constraint, Direction, Flex, Layout, Position, Rect}, layout::{Alignment, Constraint, Direction, Flex, Layout},
style::{Style, Stylize}, style::{Style, Stylize},
text::{Line, Span, Text}, text::{Line, Span, Text},
widgets::{Block, Borders, List, ListState, Paragraph}, widgets::{Block, Borders, List, ListState, Paragraph},
@ -42,8 +42,6 @@ P* - privileged *
"; ";
pub struct AppState { pub struct AppState {
/// Areas of tabs
areas: Option<Areas>,
/// Selected theme /// Selected theme
theme: Theme, theme: Theme,
/// Currently focused area /// Currently focused area
@ -82,11 +80,6 @@ pub struct ListEntry {
pub has_children: bool, pub has_children: bool,
} }
pub struct Areas {
tab_list: Rect,
list: Rect,
}
enum SelectedItem { enum SelectedItem {
UpDir, UpDir,
Directory, Directory,
@ -108,7 +101,6 @@ impl AppState {
let auto_execute_commands = config_path.map(|path| Config::from_file(&path).auto_execute); let auto_execute_commands = config_path.map(|path| Config::from_file(&path).auto_execute);
let mut state = Self { let mut state = Self {
areas: None,
theme, theme,
focus: Focus::List, focus: Focus::List,
tabs, tabs,
@ -329,11 +321,6 @@ impl AppState {
.split(horizontal[0]); .split(horizontal[0]);
frame.render_widget(label, left_chunks[0]); frame.render_widget(label, left_chunks[0]);
self.areas = Some(Areas {
tab_list: left_chunks[1],
list: horizontal[1],
});
let tabs = self let tabs = self
.tabs .tabs
.iter() .iter()
@ -488,59 +475,6 @@ impl AppState {
frame.render_widget(keybind_para, vertical[1]); frame.render_widget(keybind_para, vertical[1]);
} }
pub fn handle_mouse(&mut self, event: &MouseEvent) -> bool {
if !self.drawable {
return true;
}
if matches!(self.focus, Focus::TabList | Focus::List) {
let position = Position::new(event.column, event.row);
let mouse_in_tab_list = self.areas.as_ref().unwrap().tab_list.contains(position);
let mouse_in_list = self.areas.as_ref().unwrap().list.contains(position);
match event.kind {
MouseEventKind::Moved => {
if mouse_in_list {
self.focus = Focus::List
} else if mouse_in_tab_list {
self.focus = Focus::TabList
}
}
MouseEventKind::ScrollDown => {
if mouse_in_tab_list {
if self.current_tab.selected().unwrap() != self.tabs.len() - 1 {
self.current_tab.select_next();
}
self.refresh_tab();
} else if mouse_in_list {
self.selection.select_next()
}
}
MouseEventKind::ScrollUp => {
if mouse_in_tab_list {
if self.current_tab.selected().unwrap() != 0 {
self.current_tab.select_previous();
}
self.refresh_tab();
} else if mouse_in_list {
self.selection.select_previous()
}
}
_ => {}
}
}
match &mut self.focus {
Focus::FloatingWindow(float) => {
float.content.handle_mouse_event(event);
}
Focus::ConfirmationPrompt(confirm) => {
confirm.content.handle_mouse_event(event);
}
_ => {}
}
true
}
pub fn handle_key(&mut self, key: &KeyEvent) -> bool { pub fn handle_key(&mut self, key: &KeyEvent) -> bool {
// This should be defined first to allow closing // This should be defined first to allow closing
// the application even when not drawable ( If terminal is small ) // the application even when not drawable ( If terminal is small )