feat: use termwiz as backend as that enables a ptty, which can be cleaned up nicely
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
f0f81f8a0b
commit
348e448ce9
705
Cargo.lock
generated
705
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,6 @@ resolver = "2"
|
|||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
gitnow = { path = "crates/gitnow" }
|
|
||||||
|
|
||||||
anyhow = { version = "1" }
|
anyhow = { version = "1" }
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
|
@ -25,10 +25,10 @@ prost = "0.13.2"
|
|||||||
prost-types = "0.13.2"
|
prost-types = "0.13.2"
|
||||||
bytes = "1.7.1"
|
bytes = "1.7.1"
|
||||||
nucleo-matcher = "0.3.1"
|
nucleo-matcher = "0.3.1"
|
||||||
ratatui = "0.28.1"
|
ratatui = { version = "0.28.1", features = ["termwiz"] }
|
||||||
crossterm = { version = "0.28.0", features = ["event-stream"] }
|
crossterm = { version = "0.28.0", features = ["event-stream"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
atty = "0.2.14"
|
termwiz = "0.22.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
function git-now {
|
function git-now {
|
||||||
choice=$(gitnow "$@")
|
choice=$(gitnow "$@" --no-shell)
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
return $?
|
return $?
|
||||||
fi
|
fi
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::{collections::BTreeMap, io::IsTerminal};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::App,
|
||||||
@ -88,7 +88,7 @@ impl RootCommand {
|
|||||||
if clone {
|
if clone {
|
||||||
let git_clone = self.app.git_clone();
|
let git_clone = self.app.git_clone();
|
||||||
|
|
||||||
if atty::is(atty::Stream::Stdout) && shell {
|
if std::io::stdout().is_terminal() && shell {
|
||||||
let mut wrap_cmd =
|
let mut wrap_cmd =
|
||||||
InlineCommand::new(format!("cloning: {}", repo.to_rel_path().display()));
|
InlineCommand::new(format!("cloning: {}", repo.to_rel_path().display()));
|
||||||
let repo = repo.clone();
|
let repo = repo.clone();
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use anyhow::Error;
|
|
||||||
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
|
use tokio::sync::mpsc::{UnboundedReceiver, UnboundedSender};
|
||||||
|
|
||||||
pub mod inline_command;
|
pub mod inline_command;
|
||||||
|
@ -1,23 +1,15 @@
|
|||||||
use std::{
|
use std::time::Duration;
|
||||||
io::{stderr, Write},
|
|
||||||
time::Duration,
|
|
||||||
};
|
|
||||||
|
|
||||||
use anyhow::Context;
|
use crossterm::event::{EventStream, KeyCode};
|
||||||
use crossterm::{
|
|
||||||
event::{EventStream, KeyCode, KeyEventKind},
|
|
||||||
terminal::{enable_raw_mode, EnterAlternateScreen},
|
|
||||||
ExecutableCommand,
|
|
||||||
};
|
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
crossterm,
|
crossterm,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
widgets::{Block, Padding, Paragraph},
|
widgets::{Block, Padding},
|
||||||
TerminalOptions, Viewport,
|
TerminalOptions, Viewport,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::components::{BatchCommand, Command};
|
use crate::components::BatchCommand;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
create_dispatch,
|
create_dispatch,
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
text::{Line, Span, Text},
|
text::{Line, Span},
|
||||||
widgets::{Block, Paragraph, StatefulWidget, Widget},
|
widgets::{Block, Paragraph, StatefulWidget, Widget},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{BatchCommand, Command, IntoCommand, Msg};
|
use super::{BatchCommand, IntoCommand, Msg};
|
||||||
|
|
||||||
pub struct Spinner<'a> {
|
pub struct Spinner<'a> {
|
||||||
span: Span<'a>,
|
span: Span<'a>,
|
||||||
@ -68,8 +68,8 @@ impl Default for SpinnerState {
|
|||||||
const MINIDOT_FRAMES: [&str; 10] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
const MINIDOT_FRAMES: [&str; 10] = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
||||||
|
|
||||||
impl SpinnerState {
|
impl SpinnerState {
|
||||||
pub fn update(&mut self, msg: &Msg) -> impl IntoCommand {
|
pub fn update(&mut self, _msg: &Msg) -> impl IntoCommand {
|
||||||
let mut batch = BatchCommand::default();
|
let batch = BatchCommand::default();
|
||||||
|
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
if now.duration_since(self.last_event) >= self.interval {
|
if now.duration_since(self.last_event) >= self.interval {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{app::App, components::inline_command::InlineCommand, git_provider::Repository};
|
use crate::{app::App, git_provider::Repository};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct GitClone {
|
pub struct GitClone {
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
use std::io::stderr;
|
|
||||||
|
|
||||||
use app::App;
|
use app::App;
|
||||||
use crossterm::{
|
use ratatui::{prelude::*, Terminal};
|
||||||
terminal::{enable_raw_mode, EnterAlternateScreen},
|
|
||||||
ExecutableCommand,
|
|
||||||
};
|
|
||||||
use ratatui::{prelude::CrosstermBackend, Terminal};
|
|
||||||
|
|
||||||
use crate::git_provider::Repository;
|
use crate::git_provider::Repository;
|
||||||
|
|
||||||
@ -22,16 +16,11 @@ impl Interactive {
|
|||||||
&mut self,
|
&mut self,
|
||||||
repositories: &[Repository],
|
repositories: &[Repository],
|
||||||
) -> anyhow::Result<Option<Repository>> {
|
) -> anyhow::Result<Option<Repository>> {
|
||||||
let backend = CrosstermBackend::new(std::io::stderr());
|
let backend = TermwizBackend::new().map_err(|e| anyhow::anyhow!(e.to_string()))?;
|
||||||
let terminal = Terminal::new(backend)?;
|
let terminal = Terminal::new(backend)?;
|
||||||
|
|
||||||
enable_raw_mode()?;
|
|
||||||
stderr().execute(EnterAlternateScreen)?;
|
|
||||||
|
|
||||||
let app_result = App::new(self.app, repositories).run(terminal);
|
let app_result = App::new(self.app, repositories).run(terminal);
|
||||||
|
|
||||||
ratatui::restore();
|
|
||||||
|
|
||||||
app_result
|
app_result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -50,7 +39,7 @@ mod app {
|
|||||||
use ratatui::{
|
use ratatui::{
|
||||||
crossterm::event::{self, Event, KeyCode},
|
crossterm::event::{self, Event, KeyCode},
|
||||||
layout::{Constraint, Layout},
|
layout::{Constraint, Layout},
|
||||||
prelude::CrosstermBackend,
|
prelude::TermwizBackend,
|
||||||
style::{Style, Stylize},
|
style::{Style, Stylize},
|
||||||
text::{Line, Span},
|
text::{Line, Span},
|
||||||
widgets::{ListItem, ListState, Paragraph, StatefulWidget},
|
widgets::{ListItem, ListState, Paragraph, StatefulWidget},
|
||||||
@ -86,8 +75,6 @@ mod app {
|
|||||||
.fuzzy_matcher()
|
.fuzzy_matcher()
|
||||||
.match_repositories(&self.current_search, self.repositories);
|
.match_repositories(&self.current_search, self.repositories);
|
||||||
|
|
||||||
//res.reverse();
|
|
||||||
|
|
||||||
self.matched_repos = res;
|
self.matched_repos = res;
|
||||||
|
|
||||||
if self.list.selected().is_none() {
|
if self.list.selected().is_none() {
|
||||||
@ -95,9 +82,9 @@ mod app {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run<T: std::io::Write>(
|
pub fn run(
|
||||||
mut self,
|
mut self,
|
||||||
mut terminal: Terminal<CrosstermBackend<T>>,
|
mut terminal: Terminal<TermwizBackend>,
|
||||||
) -> anyhow::Result<Option<Repository>> {
|
) -> anyhow::Result<Option<Repository>> {
|
||||||
self.update_matched_repos();
|
self.update_matched_repos();
|
||||||
|
|
||||||
@ -117,18 +104,16 @@ mod app {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Esc => {
|
KeyCode::Esc => {
|
||||||
terminal.clear()?;
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
if let Some(selected) = self.list.selected() {
|
if let Some(selected) = self.list.selected() {
|
||||||
if let Some(repo) = self.matched_repos.get(selected).cloned() {
|
if let Some(repo) = self.matched_repos.get(selected).cloned() {
|
||||||
terminal.clear()?;
|
terminal.resize(ratatui::layout::Rect::ZERO)?;
|
||||||
return Ok(Some(repo));
|
return Ok(Some(repo));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
terminal.clear()?;
|
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
KeyCode::Up => self.list.select_next(),
|
KeyCode::Up => self.list.select_next(),
|
||||||
|
Loading…
Reference in New Issue
Block a user