T18 Terminal: a real shell on a pseudo-terminal through alacritty_terminal 0.26, drawn cell by cell in the theme's ANSI colors, with keys, text input, selection, scrollback, links and regex find; replayed output; tabs, splits and toolbar with a shell selector; command blocks and history; AnsiText, LogViewer and ProcessList
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
601a29a374
commit
8374b77906
30 files changed
+3527
-12
No files matched your search
@@ -0,0 +1,124 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use ely_gpui_component::{
|
||||
buttons::Button,
|
||||
terminal::{AnsiText, CommandBlock, CommandHistory, CommandState, PastCommand},
|
||||
typography::Caption,
|
||||
};
|
||||
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
|
||||
|
||||
use crate::ui::{keep, row, section, set};
|
||||
|
||||
const TESTS: &str = "running 5 tests\r\ntest palette::lookup_blends_toward_white ... \x1b[32mok\x1b[0m\r\ntest palette::unknown_names_fall_back ... \x1b[32mok\x1b[0m\r\n\r\ntest result: \x1b[32mok\x1b[0m. 5 passed; 0 failed; finished in 0.02s";
|
||||
|
||||
const FAILED: &str = "\x1b[1;31merror[E0308]\x1b[0m\x1b[1m: mismatched types\x1b[0m\r\n \x1b[1;34m-->\x1b[0m src/main.rs:66:21\r\n \x1b[1;34m|\x1b[0m\r\n\x1b[1;34m66\x1b[0m \x1b[1;34m|\x1b[0m let count: u32 = tints.len();\r\n \x1b[1;34m|\x1b[0m \x1b[1;34m---\x1b[0m \x1b[1;31m^^^^^^^^^^^\x1b[0m \x1b[1;31mexpected `u32`, found `usize`\x1b[0m";
|
||||
|
||||
fn history() -> Vec<PastCommand> {
|
||||
let past = |command: &str, cwd: &str, when: &str, code| PastCommand {
|
||||
command: command.to_string().into(),
|
||||
cwd: cwd.to_string().into(),
|
||||
when: when.to_string().into(),
|
||||
code,
|
||||
};
|
||||
vec![
|
||||
past("cargo test --lib palette", "~/palette", "just now", Some(0)),
|
||||
past("cargo build", "~/palette", "2 min ago", Some(101)),
|
||||
past("git status --short", "~/palette", "5 min ago", Some(0)),
|
||||
past("rg lookup src", "~/palette", "12 min ago", Some(0)),
|
||||
past(
|
||||
"cargo run --example gallery",
|
||||
"~/Ely-GPUI-Components",
|
||||
"1 h ago",
|
||||
None,
|
||||
),
|
||||
past(
|
||||
"git log --oneline -5",
|
||||
"~/Ely-GPUI-Components",
|
||||
"yesterday",
|
||||
Some(0),
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
pub fn blocks(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let folded = keep("terminal-folded", || false, window, cx);
|
||||
let open = keep("terminal-history", || false, window, cx);
|
||||
let said = keep("terminal-said", || None::<SharedString>, window, cx);
|
||||
let (now_folded, now_open, told) = (*folded.read(cx), *open.read(cx), said.read(cx).clone());
|
||||
let (fold, opener, close, pick, rerun) = (
|
||||
folded.clone(),
|
||||
open.clone(),
|
||||
open.clone(),
|
||||
said.clone(),
|
||||
said.clone(),
|
||||
);
|
||||
section(
|
||||
"CommandBlock / CommandHistory",
|
||||
"Each command a block: where it ran, how it ended and how long it took, its output folding away; copy it or run it again. Past commands open as a palette, found by any of their letters.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(840.))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(CommandBlock::new(
|
||||
"terminal-block-tests",
|
||||
"~/palette",
|
||||
"cargo test --lib palette",
|
||||
TESTS,
|
||||
CommandState::Done {
|
||||
code: 0,
|
||||
took: Duration::from_secs(3),
|
||||
},
|
||||
))
|
||||
.child(
|
||||
CommandBlock::new(
|
||||
"terminal-block-build",
|
||||
"~/palette",
|
||||
"cargo build",
|
||||
FAILED,
|
||||
CommandState::Done {
|
||||
code: 101,
|
||||
took: Duration::from_secs(9),
|
||||
},
|
||||
)
|
||||
.folded(now_folded)
|
||||
.on_fold(move |folded, _, cx| set(&fold, folded, cx))
|
||||
.on_rerun(move |_, cx| set(&rerun, Some("Ran cargo build again.".into()), cx)),
|
||||
)
|
||||
.child(CommandBlock::new(
|
||||
"terminal-block-running",
|
||||
"~/Ely-GPUI-Components",
|
||||
"cargo run --example gallery",
|
||||
"",
|
||||
CommandState::Running,
|
||||
)),
|
||||
)
|
||||
.child(row().child(Button::new("terminal-history-open", "Search history…").on_click(move |_, _, cx| set(&opener, true, cx))))
|
||||
.children(told.map(Caption::new))
|
||||
.children(now_open.then(|| {
|
||||
CommandHistory::new("terminal-history-palette", history(), move |_, cx| set(&close, false, cx))
|
||||
.on_pick(move |command, _, cx| set(&pick, Some(format!("Ran {command}.").into()), cx))
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn ansi(cx: &mut App) -> impl IntoElement + use<> {
|
||||
section(
|
||||
"AnsiText",
|
||||
"Text colored by the escape codes in it, as a terminal prints it: the sixteen theme colors, bold, dim, italic, underline, inverse, the 256-color cube and true color. Other codes drop away.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w(px(840.))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.child(AnsiText::new("\x1b[30m■\x1b[31m■\x1b[32m■\x1b[33m■\x1b[34m■\x1b[35m■\x1b[36m■\x1b[37m■ \x1b[90m■\x1b[91m■\x1b[92m■\x1b[93m■\x1b[94m■\x1b[95m■\x1b[96m■\x1b[97m■\x1b[0m the sixteen, dark and bright"))
|
||||
.child(AnsiText::new("\x1b[1mbold\x1b[0m \x1b[2mdim\x1b[0m \x1b[3mitalic\x1b[0m \x1b[4munderline\x1b[0m \x1b[9mstruck\x1b[0m \x1b[7m inverse \x1b[0m"))
|
||||
.child(AnsiText::new("\x1b[38;5;24m██\x1b[38;5;30m██\x1b[38;5;36m██\x1b[38;5;72m██\x1b[38;5;108m██\x1b[38;5;144m██\x1b[38;5;180m██\x1b[38;5;216m██\x1b[0m the cube \x1b[38;2;81;130;193m██\x1b[38;2;0;149;137m██\x1b[38;2;170;115;43m██\x1b[0m true color"))
|
||||
.child(AnsiText::new("\x1b[42;30m PASS \x1b[0m palette \x1b[41;97m FAIL \x1b[0m tokens \x1b[43;30m SKIP \x1b[0m motion")),
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user