mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
Merge branch 'main' into ssh-integration
This commit is contained in:
@ -14,26 +14,6 @@ struct TerminalEntity: AppEntity {
|
||||
@Property(title: "Kind")
|
||||
var kind: Kind
|
||||
|
||||
@MainActor
|
||||
@DeferredProperty(title: "Full Contents")
|
||||
@available(macOS 26.0, *)
|
||||
var screenContents: String? {
|
||||
get async {
|
||||
guard let surfaceView else { return nil }
|
||||
return surfaceView.cachedScreenContents.get()
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
@DeferredProperty(title: "Visible Contents")
|
||||
@available(macOS 26.0, *)
|
||||
var visibleContents: String? {
|
||||
get async {
|
||||
guard let surfaceView else { return nil }
|
||||
return surfaceView.cachedVisibleContents.get()
|
||||
}
|
||||
}
|
||||
|
||||
var screenshot: Image?
|
||||
|
||||
static var typeDisplayRepresentation: TypeDisplayRepresentation {
|
||||
|
@ -148,6 +148,18 @@ const locales = [_][]const u8{
|
||||
|
||||
You should then be able to run `zig build` and see your translations in action.
|
||||
|
||||
Before opening a pull request with the new translation file, you should also add
|
||||
your locale to the `CODEOWNERS` file. Find the `# Localization` section near the
|
||||
bottom and add a line like so (where `xx_YY` is your locale):
|
||||
|
||||
```diff
|
||||
# Localization
|
||||
/po/README_TRANSLATORS.md @ghostty-org/localization
|
||||
/po/com.mitchellh.ghostty.pot @ghostty-org/localization
|
||||
/po/zh_CN.UTF-8.po @ghostty-org/zh_CN
|
||||
+/po/xx_YY.UTF-8.po @ghostty-org/xx_YY
|
||||
```
|
||||
|
||||
## Style Guide
|
||||
|
||||
These are general style guidelines for translations. Naturally, the specific
|
||||
|
@ -1034,6 +1034,12 @@ fn childExited(self: *Surface, info: apprt.surface.Message.ChildExited) void {
|
||||
t.printString("Process exited. Press any key to close the terminal.") catch
|
||||
break :terminal;
|
||||
t.modes.set(.cursor_visible, false);
|
||||
|
||||
// We also want to ensure that normal keyboard encoding is on
|
||||
// so that we can close the terminal. We close the terminal on
|
||||
// any key press that encodes a character.
|
||||
t.modes.set(.disable_keyboard, false);
|
||||
t.screen.kitty_keyboard.set(.set, .{});
|
||||
}
|
||||
|
||||
// Waiting after command we stop here. The terminal is updated, our
|
||||
@ -2129,14 +2135,6 @@ pub fn keyCallback(
|
||||
if (self.io.terminal.modes.get(.disable_keyboard)) return .consumed;
|
||||
}
|
||||
|
||||
// If our process is exited and we press a key then we close the
|
||||
// surface. We may want to eventually move this to the apprt rather
|
||||
// than in core.
|
||||
if (self.child_exited and event.action == .press) {
|
||||
self.close();
|
||||
return .closed;
|
||||
}
|
||||
|
||||
// If this input event has text, then we hide the mouse if configured.
|
||||
// We only do this on pressed events to avoid hiding the mouse when we
|
||||
// change focus due to a keybinding (i.e. switching tabs).
|
||||
@ -2231,6 +2229,14 @@ pub fn keyCallback(
|
||||
event,
|
||||
if (insp_ev) |*ev| ev else null,
|
||||
)) |write_req| {
|
||||
// If our process is exited and we press a key that results in
|
||||
// an encoded value, we close the surface. We want to eventually
|
||||
// move this behavior to the apprt probably.
|
||||
if (self.child_exited) {
|
||||
self.close();
|
||||
return .closed;
|
||||
}
|
||||
|
||||
errdefer write_req.deinit();
|
||||
self.io.queueMessage(switch (write_req) {
|
||||
.small => |v| .{ .write_small = v },
|
||||
|
@ -103,11 +103,12 @@ pub const Contents = struct {
|
||||
// form a single grapheme, and multi-substitutions in fonts, the number
|
||||
// of glyphs in a row is theoretically unlimited.
|
||||
//
|
||||
// We have size.rows + 1 lists because index 0 is used for a special
|
||||
// list containing the cursor cell which needs to be first in the buffer.
|
||||
// We have size.rows + 2 lists because indexes 0 and size.rows - 1 are
|
||||
// used for special lists containing the cursor cell which need to
|
||||
// be first and last in the buffer, respectively.
|
||||
var fg_rows = try ArrayListCollection(shaderpkg.CellText).init(
|
||||
alloc,
|
||||
size.rows + 1,
|
||||
size.rows + 2,
|
||||
size.columns * 3,
|
||||
);
|
||||
errdefer fg_rows.deinit(alloc);
|
||||
@ -118,14 +119,19 @@ pub const Contents = struct {
|
||||
self.bg_cells = bg_cells;
|
||||
self.fg_rows = fg_rows;
|
||||
|
||||
// We don't need 3*cols worth of cells for the cursor list, so we can
|
||||
// replace it with a smaller list. This is technically a tiny bit of
|
||||
// We don't need 3*cols worth of cells for the cursor lists, so we can
|
||||
// replace them with smaller lists. This is technically a tiny bit of
|
||||
// extra work but resize is not a hot function so it's worth it to not
|
||||
// waste the memory.
|
||||
self.fg_rows.lists[0].deinit(alloc);
|
||||
self.fg_rows.lists[0] = try std.ArrayListUnmanaged(
|
||||
shaderpkg.CellText,
|
||||
).initCapacity(alloc, 1);
|
||||
|
||||
self.fg_rows.lists[size.rows + 1].deinit(alloc);
|
||||
self.fg_rows.lists[size.rows + 1] = try std.ArrayListUnmanaged(
|
||||
shaderpkg.CellText,
|
||||
).initCapacity(alloc, 1);
|
||||
}
|
||||
|
||||
/// Reset the cell contents to an empty state without resizing.
|
||||
@ -135,11 +141,18 @@ pub const Contents = struct {
|
||||
}
|
||||
|
||||
/// Set the cursor value. If the value is null then the cursor is hidden.
|
||||
pub fn setCursor(self: *Contents, v: ?shaderpkg.CellText) void {
|
||||
pub fn setCursor(self: *Contents, v: ?shaderpkg.CellText, cursor_style: ?renderer.CursorStyle) void {
|
||||
self.fg_rows.lists[0].clearRetainingCapacity();
|
||||
self.fg_rows.lists[self.size.rows + 1].clearRetainingCapacity();
|
||||
|
||||
if (v) |cell| {
|
||||
self.fg_rows.lists[0].appendAssumeCapacity(cell);
|
||||
const cell = v orelse return;
|
||||
const style = cursor_style orelse return;
|
||||
|
||||
switch (style) {
|
||||
// Block cursors should be drawn first
|
||||
.block => self.fg_rows.lists[0].appendAssumeCapacity(cell),
|
||||
// Other cursor styles should be drawn last
|
||||
.block_hollow, .bar, .underline, .lock => self.fg_rows.lists[self.size.rows + 1].appendAssumeCapacity(cell),
|
||||
}
|
||||
}
|
||||
|
||||
@ -367,18 +380,22 @@ test Contents {
|
||||
}
|
||||
}
|
||||
|
||||
// Add a cursor.
|
||||
// Add a block cursor.
|
||||
const cursor_cell: shaderpkg.CellText = .{
|
||||
.mode = .cursor,
|
||||
.grid_pos = .{ 2, 3 },
|
||||
.color = .{ 0, 0, 0, 1 },
|
||||
};
|
||||
c.setCursor(cursor_cell);
|
||||
c.setCursor(cursor_cell, .block);
|
||||
try testing.expectEqual(cursor_cell, c.fg_rows.lists[0].items[0]);
|
||||
|
||||
// And remove it.
|
||||
c.setCursor(null);
|
||||
c.setCursor(null, null);
|
||||
try testing.expectEqual(0, c.fg_rows.lists[0].items.len);
|
||||
|
||||
// Add a hollow cursor.
|
||||
c.setCursor(cursor_cell, .block_hollow);
|
||||
try testing.expectEqual(cursor_cell, c.fg_rows.lists[rows + 1].items[0]);
|
||||
}
|
||||
|
||||
test "Contents clear retains other content" {
|
||||
|
@ -2791,7 +2791,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
// Setup our cursor rendering information.
|
||||
cursor: {
|
||||
// By default, we don't handle cursor inversion on the shader.
|
||||
self.cells.setCursor(null);
|
||||
self.cells.setCursor(null, null);
|
||||
self.uniforms.cursor_pos = .{
|
||||
std.math.maxInt(u16),
|
||||
std.math.maxInt(u16),
|
||||
@ -3162,7 +3162,7 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
|
||||
@intCast(render.glyph.offset_x),
|
||||
@intCast(render.glyph.offset_y),
|
||||
},
|
||||
});
|
||||
}, cursor_style);
|
||||
}
|
||||
|
||||
fn addPreeditCell(
|
||||
|
@ -270,7 +270,6 @@ _ghostty_last_reported_cwd=""
|
||||
function __ghostty_precmd() {
|
||||
local ret="$?"
|
||||
if test "$_ghostty_executing" != "0"; then
|
||||
_GHOSTTY_SAVE_PS0="$PS0"
|
||||
_GHOSTTY_SAVE_PS1="$PS1"
|
||||
_GHOSTTY_SAVE_PS2="$PS2"
|
||||
|
||||
@ -287,8 +286,8 @@ function __ghostty_precmd() {
|
||||
|
||||
# Cursor
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *"cursor"* ]]; then
|
||||
PS1=$PS1'\[\e[5 q\]'
|
||||
PS0=$PS0'\[\e[0 q\]'
|
||||
PS1=$PS1'\[\e[5 q\]' # blinking bar for input
|
||||
builtin printf "\e[0 q" # reset to default cursor
|
||||
fi
|
||||
|
||||
# Title (working directory)
|
||||
@ -318,7 +317,6 @@ function __ghostty_precmd() {
|
||||
function __ghostty_preexec() {
|
||||
builtin local cmd="$1"
|
||||
|
||||
PS0="$_GHOSTTY_SAVE_PS0"
|
||||
PS1="$_GHOSTTY_SAVE_PS1"
|
||||
PS2="$_GHOSTTY_SAVE_PS2"
|
||||
|
||||
|
Reference in New Issue
Block a user