T22: Edit's Copy, Paste and Select All are Ely's text input actions, which Ely a2cb531 exports and the terminal handles too, so the menu reaches find and every field; Select All counts a space under a combining mark as a character; comments cut to one short line; the Ely pin moves to a2cb531; AGENTS.md says gpui draws a shot window only while macOS shows it
This commit is contained in:
11 files changed
+56
-39
No files matched your search
+3
-2
@@ -1,6 +1,7 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use alacritty_terminal::{grid::Scroll, term::TermMode};
|
||||
use ely_gpui_component::forms::{Copy, Paste, SelectAll};
|
||||
use gpui::{
|
||||
App, Bounds, Context, EntityInputHandler, KeyBinding, KeyDownEvent, KeyUpEvent, Keystroke,
|
||||
NoAction, Pixels, Point, UTF16Selection, Window, actions,
|
||||
@@ -11,7 +12,7 @@ use super::{
|
||||
view::TerminalView,
|
||||
};
|
||||
|
||||
actions!(elyterminal, [Copy, Paste, Find, FindNewer, SelectAll]);
|
||||
actions!(elyterminal, [Find, FindNewer]);
|
||||
|
||||
/// The key context a terminal's root sets.
|
||||
pub const CONTEXT: &str = "Terminal";
|
||||
@@ -19,7 +20,7 @@ pub const CONTEXT: &str = "Terminal";
|
||||
/// The key context of a terminal's find box.
|
||||
pub const FIND: &str = "TerminalFind";
|
||||
|
||||
/// Copy, paste, select all and find; Ely's focus keys go to the terminal's listeners instead.
|
||||
/// The terminal's keys; Ely's focus keys reach its listeners.
|
||||
pub fn bind_keys(cx: &mut App) {
|
||||
let (copy, paste, all, find) = if cfg!(target_os = "macos") {
|
||||
("cmd-c", "cmd-v", "cmd-a", "cmd-f")
|
||||
|
||||
+25
-10
@@ -298,7 +298,7 @@ impl TerminalView {
|
||||
(!text.is_empty()).then_some(text)
|
||||
}
|
||||
|
||||
/// Selects the history and the screen, blanks around them left out; copy on select takes the text.
|
||||
/// Selects all text; copy on select takes it.
|
||||
pub(super) fn select_all(&mut self, cx: &mut Context<Self>) {
|
||||
{
|
||||
let mut term = self.pty.term.lock();
|
||||
@@ -367,13 +367,17 @@ impl TerminalView {
|
||||
}
|
||||
}
|
||||
|
||||
/// Ghostty's select all: the first cell holding more than a space or tab, through history and screen, to the last.
|
||||
/// Ghostty's select all: first to last non-blank cell.
|
||||
fn everything<T>(term: &Term<T>) -> Option<Selection> {
|
||||
let grid = term.grid();
|
||||
let cells = (grid.topmost_line().0..=grid.bottommost_line().0).flat_map(|line| {
|
||||
(0..grid.columns()).map(move |column| Cell::new(Line(line), Column(column)))
|
||||
});
|
||||
let inked = |cell: &Cell| !matches!(grid[*cell].c, ' ' | '\t');
|
||||
let inked = |point: &Cell| {
|
||||
let cell = &grid[*point];
|
||||
let marked = cell.zerowidth().is_some_and(|marks| !marks.is_empty());
|
||||
marked || !matches!(cell.c, ' ' | '\t')
|
||||
};
|
||||
let first = cells.clone().find(inked)?;
|
||||
let last = cells.rev().find(inked)?;
|
||||
let mut all = Selection::new(SelectionType::Simple, first, Side::Left);
|
||||
@@ -391,14 +395,25 @@ mod tests {
|
||||
|
||||
use super::*;
|
||||
|
||||
/// What select all copies after `bytes`.
|
||||
fn all(bytes: &[u8]) -> Option<String> {
|
||||
let mut term = Term::new(Config::default(), &TermSize::new(10, 3), VoidListener);
|
||||
let mut parser: Processor = Processor::new();
|
||||
parser.advance(&mut term, bytes);
|
||||
term.selection = everything(&term);
|
||||
term.selection_to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn everything_runs_from_the_first_character_in_the_history_to_the_last() {
|
||||
let mut term = Term::new(Config::default(), &TermSize::new(10, 3), VoidListener);
|
||||
assert!(everything(&term).is_none(), "a blank grid selects nothing");
|
||||
let mut parser: Processor = Processor::new();
|
||||
parser.advance(&mut term, b"\r\n one\r\n\r\ntwo six\t\r\n\r\n");
|
||||
term.selection = everything(&term);
|
||||
let text = term.selection_to_string().expect("a selection");
|
||||
assert_eq!(text, "one\n\ntwo six");
|
||||
assert_eq!(all(b""), None, "a blank grid selects nothing");
|
||||
let text = all(b"\r\n one\r\n\r\ntwo six\t\r\n\r\n");
|
||||
assert_eq!(text.as_deref(), Some("one\n\ntwo six"));
|
||||
let mark = all(" \u{301}".as_bytes());
|
||||
assert_eq!(mark.as_deref(), Some(" \u{301}"), "a mark on a space");
|
||||
let last = all("text \u{301}".as_bytes());
|
||||
assert_eq!(last.as_deref(), Some("text \u{301}"), "a mark ends it");
|
||||
let link = all(b"\x1b]8;;http://a\x07 \x1b]8;;\x07text");
|
||||
assert_eq!(link.as_deref(), Some("text"), "a linked space is blank");
|
||||
}
|
||||
}
|
||||
+6
-3
@@ -6,7 +6,10 @@ use alacritty_terminal::{
|
||||
term::{ClipboardType, TermMode},
|
||||
vte::ansi::CursorShape,
|
||||
};
|
||||
use ely_gpui_component::theme::ActiveTheme;
|
||||
use ely_gpui_component::{
|
||||
forms::{Copy, Paste, SelectAll},
|
||||
theme::ActiveTheme,
|
||||
};
|
||||
use futures::StreamExt;
|
||||
use gpui::{
|
||||
Bounds, Context, EventEmitter, FocusHandle, Focusable, Font, FontFeatures, FontId, FontStyle,
|
||||
@@ -18,7 +21,7 @@ use super::{
|
||||
find::Finder,
|
||||
frame::frame,
|
||||
ink::Ink,
|
||||
input::{self, Copy, Find, Paste, SelectAll},
|
||||
input::{self, Find},
|
||||
mouse::MouseMode,
|
||||
paint::{self, Look},
|
||||
pointer::Pointer,
|
||||
@@ -269,7 +272,7 @@ pub fn load_font(font: &Font, system: &TextSystem) -> anyhow::Result<FontId> {
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// The font, cell and metrics the settings give at `points` and this window's scale.
|
||||
/// Font, cell and metrics at `points` on this window.
|
||||
fn look(settings: &Settings, points: f32, ink: &Ink, window: &Window) -> anyhow::Result<Look> {
|
||||
let font = Font {
|
||||
family: settings.font_family.clone().into(),
|
||||
|
||||
+4
-4
@@ -2,18 +2,18 @@ use gpui::{App, Global};
|
||||
|
||||
use crate::settings::{FONT_SIZE, SettingsStore};
|
||||
|
||||
/// Points the terminal's font stands above the Size setting, below it when negative; Bigger and Smaller move it, nothing saves it.
|
||||
/// Unsaved font-size offset.
|
||||
#[derive(Default)]
|
||||
pub struct Enlarged(f32);
|
||||
|
||||
impl Global for Enlarged {}
|
||||
|
||||
/// The size the terminal draws its font at: the setting, moved, inside the range.
|
||||
/// The font size the terminal draws.
|
||||
pub fn size(cx: &App) -> f32 {
|
||||
shown(SettingsStore::get(cx).font_size, cx.global::<Enlarged>().0)
|
||||
}
|
||||
|
||||
/// Moves the font `by` points, or back to the setting when `by` is none.
|
||||
/// Moves the font `by` points; none resets it.
|
||||
pub fn step(by: Option<f32>, cx: &mut App) {
|
||||
let setting = SettingsStore::get(cx).font_size;
|
||||
let enlarged = by.map_or(0.0, |by| moved(setting, cx.global::<Enlarged>().0, by));
|
||||
@@ -28,7 +28,7 @@ fn shown(setting: f32, enlarged: f32) -> f32 {
|
||||
(setting + enlarged).clamp(*FONT_SIZE.start(), *FONT_SIZE.end())
|
||||
}
|
||||
|
||||
/// What `enlarged` becomes once the font moves `by` points from where it shows.
|
||||
/// The offset after moving `by` from the shown size.
|
||||
fn moved(setting: f32, enlarged: f32, by: f32) -> f32 {
|
||||
shown(shown(setting, enlarged) + by, 0.0) - setting
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user