mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-25 13:16:11 +03:00
Merge branch 'main' into jacob/zg
This commit is contained in:
20
.github/workflows/release-pr.yml
vendored
20
.github/workflows/release-pr.yml
vendored
@ -147,14 +147,16 @@ jobs:
|
||||
|
||||
- name: "Notarize app bundle"
|
||||
env:
|
||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||
APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
run: |
|
||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||
# from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||
echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
|
||||
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
|
||||
rm notarization_key.p8
|
||||
|
||||
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
||||
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
||||
@ -299,14 +301,16 @@ jobs:
|
||||
|
||||
- name: "Notarize app bundle"
|
||||
env:
|
||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||
APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
run: |
|
||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||
# from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||
echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
|
||||
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
|
||||
rm notarization_key.p8
|
||||
|
||||
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
||||
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
||||
|
10
.github/workflows/release-tag.yml
vendored
10
.github/workflows/release-tag.yml
vendored
@ -229,14 +229,16 @@ jobs:
|
||||
|
||||
- name: "Notarize DMG"
|
||||
env:
|
||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||
APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
run: |
|
||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||
# from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||
echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
|
||||
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
|
||||
rm notarization_key.p8
|
||||
|
||||
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
||||
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
||||
|
30
.github/workflows/release-tip.yml
vendored
30
.github/workflows/release-tip.yml
vendored
@ -267,14 +267,16 @@ jobs:
|
||||
|
||||
- name: "Notarize DMG"
|
||||
env:
|
||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||
APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
run: |
|
||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||
# from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||
echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
|
||||
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
|
||||
rm notarization_key.p8
|
||||
|
||||
# Here we send the notarization request to the Apple's Notarization service, waiting for the result.
|
||||
# This typically takes a few seconds inside a CI environment, but it might take more depending on the App
|
||||
@ -471,14 +473,16 @@ jobs:
|
||||
|
||||
- name: "Notarize app bundle"
|
||||
env:
|
||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||
APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
run: |
|
||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||
# from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||
echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
|
||||
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
|
||||
rm notarization_key.p8
|
||||
|
||||
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
||||
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
||||
@ -646,14 +650,16 @@ jobs:
|
||||
|
||||
- name: "Notarize app bundle"
|
||||
env:
|
||||
PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_APPLE_ID }}
|
||||
PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.PROD_MACOS_NOTARIZATION_TEAM_ID }}
|
||||
PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.PROD_MACOS_NOTARIZATION_PWD }}
|
||||
APPLE_NOTARIZATION_ISSUER: ${{ secrets.APPLE_NOTARIZATION_ISSUER }}
|
||||
APPLE_NOTARIZATION_KEY_ID: ${{ secrets.APPLE_NOTARIZATION_KEY_ID }}
|
||||
APPLE_NOTARIZATION_KEY: ${{ secrets.APPLE_NOTARIZATION_KEY }}
|
||||
run: |
|
||||
# Store the notarization credentials so that we can prevent a UI password dialog
|
||||
# from blocking the CI
|
||||
echo "Create keychain profile"
|
||||
xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD"
|
||||
echo "$APPLE_NOTARIZATION_KEY" > notarization_key.p8
|
||||
xcrun notarytool store-credentials "notarytool-profile" --key notarization_key.p8 --key-id "$APPLE_NOTARIZATION_KEY_ID" --issuer "$APPLE_NOTARIZATION_ISSUER"
|
||||
rm notarization_key.p8
|
||||
|
||||
# We can't notarize an app bundle directly, but we need to compress it as an archive.
|
||||
# Therefore, we create a zip file containing our app bundle, so that we can send it to the
|
||||
|
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
@ -561,7 +561,16 @@ jobs:
|
||||
name: ghostty
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
|
||||
- name: Test GTK Build
|
||||
- name: Test
|
||||
run: |
|
||||
nix develop -c \
|
||||
zig build \
|
||||
-Dapp-runtime=gtk \
|
||||
-Dgtk-x11=${{ matrix.x11 }} \
|
||||
-Dgtk-wayland=${{ matrix.wayland }} \
|
||||
test
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
nix develop -c \
|
||||
zig build \
|
||||
|
@ -181,6 +181,7 @@
|
||||
/po/zh_CN.UTF-8.po @ghostty-org/zh_CN
|
||||
/po/ga_IE.UTF-8.po @ghostty-org/ga_IE
|
||||
/po/ko_KR.UTF-8.po @ghostty-org/ko_KR
|
||||
/po/he_IL.UTF-8.po @ghostty-org/he_IL
|
||||
|
||||
# Packaging - Snap
|
||||
/snap/ @ghostty-org/snap
|
||||
|
5
dist/linux/systemd.service.in
vendored
5
dist/linux/systemd.service.in
vendored
@ -1,9 +1,12 @@
|
||||
[Unit]
|
||||
Description=@NAME@
|
||||
After=graphical-session.target
|
||||
After=dbus.socket
|
||||
Requires=dbus.socket
|
||||
|
||||
[Service]
|
||||
Type=dbus
|
||||
Type=notify-reload
|
||||
ReloadSignal=SIGUSR2
|
||||
BusName=@APPID@
|
||||
ExecStart=@GHOSTTY@ --launched-from=systemd
|
||||
|
||||
|
@ -350,6 +350,11 @@ typedef struct {
|
||||
const char* message;
|
||||
} ghostty_diagnostic_s;
|
||||
|
||||
typedef struct {
|
||||
const char* ptr;
|
||||
uintptr_t len;
|
||||
} ghostty_string_s;
|
||||
|
||||
typedef struct {
|
||||
double tl_px_x;
|
||||
double tl_px_y;
|
||||
@ -797,6 +802,7 @@ int ghostty_init(uintptr_t, char**);
|
||||
void ghostty_cli_try_action(void);
|
||||
ghostty_info_s ghostty_info(void);
|
||||
const char* ghostty_translate(const char*);
|
||||
void ghostty_string_free(ghostty_string_s);
|
||||
|
||||
ghostty_config_t ghostty_config_new();
|
||||
void ghostty_config_free(ghostty_config_t);
|
||||
@ -811,7 +817,7 @@ ghostty_input_trigger_s ghostty_config_trigger(ghostty_config_t,
|
||||
uintptr_t);
|
||||
uint32_t ghostty_config_diagnostics_count(ghostty_config_t);
|
||||
ghostty_diagnostic_s ghostty_config_get_diagnostic(ghostty_config_t, uint32_t);
|
||||
void ghostty_config_open();
|
||||
ghostty_string_s ghostty_config_open_path(void);
|
||||
|
||||
ghostty_app_t ghostty_app_new(const ghostty_runtime_config_s*,
|
||||
ghostty_config_t);
|
||||
|
@ -14,6 +14,7 @@
|
||||
9351BE8E3D22937F003B3499 /* nvim in Resources */ = {isa = PBXBuildFile; fileRef = 9351BE8E2D22937F003B3499 /* nvim */; };
|
||||
A50297352DFA0F3400B4E924 /* Double+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A50297342DFA0F3300B4E924 /* Double+Extension.swift */; };
|
||||
A505D21D2E1A2FA20018808F /* FileHandle+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A505D21C2E1A2F9E0018808F /* FileHandle+Extension.swift */; };
|
||||
A505D21F2E1B6DE00018808F /* NSWorkspace+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A505D21E2E1B6DDC0018808F /* NSWorkspace+Extension.swift */; };
|
||||
A511940F2E050595007258CC /* CloseTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A511940E2E050590007258CC /* CloseTerminalIntent.swift */; };
|
||||
A51194112E05A483007258CC /* QuickTerminalIntent.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51194102E05A480007258CC /* QuickTerminalIntent.swift */; };
|
||||
A51194132E05D006007258CC /* Optional+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = A51194122E05D003007258CC /* Optional+Extension.swift */; };
|
||||
@ -160,6 +161,7 @@
|
||||
9351BE8E2D22937F003B3499 /* nvim */ = {isa = PBXFileReference; lastKnownFileType = folder; name = nvim; path = "../zig-out/share/nvim"; sourceTree = "<group>"; };
|
||||
A50297342DFA0F3300B4E924 /* Double+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Double+Extension.swift"; sourceTree = "<group>"; };
|
||||
A505D21C2E1A2F9E0018808F /* FileHandle+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileHandle+Extension.swift"; sourceTree = "<group>"; };
|
||||
A505D21E2E1B6DDC0018808F /* NSWorkspace+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSWorkspace+Extension.swift"; sourceTree = "<group>"; };
|
||||
A511940E2E050590007258CC /* CloseTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseTerminalIntent.swift; sourceTree = "<group>"; };
|
||||
A51194102E05A480007258CC /* QuickTerminalIntent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickTerminalIntent.swift; sourceTree = "<group>"; };
|
||||
A51194122E05D003007258CC /* Optional+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Optional+Extension.swift"; sourceTree = "<group>"; };
|
||||
@ -531,6 +533,7 @@
|
||||
AEE8B3442B9AA39600260C5E /* NSPasteboard+Extension.swift */,
|
||||
C1F26EA62B738B9900404083 /* NSView+Extension.swift */,
|
||||
A5874D9C2DAD785F00E83852 /* NSWindow+Extension.swift */,
|
||||
A505D21E2E1B6DDC0018808F /* NSWorkspace+Extension.swift */,
|
||||
A5985CD62C320C4500C57AD3 /* String+Extension.swift */,
|
||||
A58636722DF4813000E04A10 /* UndoManager+Extension.swift */,
|
||||
A5CC36142C9CDA03004D6760 /* View+Extension.swift */,
|
||||
@ -819,6 +822,7 @@
|
||||
A5CC36152C9CDA06004D6760 /* View+Extension.swift in Sources */,
|
||||
A56D58892ACDE6CA00508D2C /* ServiceProvider.swift in Sources */,
|
||||
A5CBD0602CA0C90A0017A1AE /* QuickTerminalWindow.swift in Sources */,
|
||||
A505D21F2E1B6DE00018808F /* NSWorkspace+Extension.swift in Sources */,
|
||||
A5CBD05E2CA0C5EC0017A1AE /* QuickTerminalController.swift in Sources */,
|
||||
A5CF66D72D29DDB500139794 /* Ghostty.Event.swift in Sources */,
|
||||
A511940F2E050595007258CC /* CloseTerminalIntent.swift in Sources */,
|
||||
|
@ -932,7 +932,7 @@ class AppDelegate: NSObject,
|
||||
//MARK: - IB Actions
|
||||
|
||||
@IBAction func openConfig(_ sender: Any?) {
|
||||
ghostty.openConfig()
|
||||
Ghostty.App.openConfig()
|
||||
}
|
||||
|
||||
@IBAction func reloadConfig(_ sender: Any?) {
|
||||
|
@ -40,4 +40,34 @@ extension Ghostty.Action {
|
||||
self.amount = c.amount
|
||||
}
|
||||
}
|
||||
|
||||
struct OpenURL {
|
||||
enum Kind {
|
||||
case unknown
|
||||
case text
|
||||
|
||||
init(_ c: ghostty_action_open_url_kind_e) {
|
||||
switch c {
|
||||
case GHOSTTY_ACTION_OPEN_URL_KIND_TEXT:
|
||||
self = .text
|
||||
default:
|
||||
self = .unknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let kind: Kind
|
||||
let url: String
|
||||
|
||||
init(c: ghostty_action_open_url_s) {
|
||||
self.kind = Kind(c.kind)
|
||||
|
||||
if let urlCString = c.url {
|
||||
let data = Data(bytes: urlCString, count: Int(c.len))
|
||||
self.url = String(data: data, encoding: .utf8) ?? ""
|
||||
} else {
|
||||
self.url = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -114,9 +114,21 @@ extension Ghostty {
|
||||
ghostty_app_tick(app)
|
||||
}
|
||||
|
||||
func openConfig() {
|
||||
guard let app = self.app else { return }
|
||||
ghostty_app_open_config(app)
|
||||
static func openConfig() {
|
||||
let str = Ghostty.AllocatedString(ghostty_config_open_path()).string
|
||||
guard !str.isEmpty else { return }
|
||||
#if os(macOS)
|
||||
let fileURL = URL(fileURLWithPath: str).absoluteString
|
||||
var action = ghostty_action_open_url_s()
|
||||
action.kind = GHOSTTY_ACTION_OPEN_URL_KIND_TEXT
|
||||
fileURL.withCString { cStr in
|
||||
action.url = cStr
|
||||
action.len = UInt(fileURL.count)
|
||||
_ = openURL(action)
|
||||
}
|
||||
#else
|
||||
fatalError("Unsupported platform for opening config file")
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Reload the configuration.
|
||||
@ -488,7 +500,7 @@ extension Ghostty {
|
||||
pwdChanged(app, target: target, v: action.action.pwd)
|
||||
|
||||
case GHOSTTY_ACTION_OPEN_CONFIG:
|
||||
ghostty_config_open()
|
||||
openConfig()
|
||||
|
||||
case GHOSTTY_ACTION_FLOAT_WINDOW:
|
||||
toggleFloatWindow(app, target: target, mode: action.action.float_window)
|
||||
@ -546,6 +558,9 @@ extension Ghostty {
|
||||
|
||||
case GHOSTTY_ACTION_CHECK_FOR_UPDATES:
|
||||
checkForUpdates(app)
|
||||
|
||||
case GHOSTTY_ACTION_OPEN_URL:
|
||||
return openURL(action.action.open_url)
|
||||
|
||||
case GHOSTTY_ACTION_UNDO:
|
||||
return undo(app, target: target)
|
||||
@ -598,6 +613,34 @@ extension Ghostty {
|
||||
appDelegate.checkForUpdates(nil)
|
||||
}
|
||||
}
|
||||
|
||||
private static func openURL(
|
||||
_ v: ghostty_action_open_url_s
|
||||
) -> Bool {
|
||||
let action = Ghostty.Action.OpenURL(c: v)
|
||||
|
||||
// Convert the URL string to a URL object
|
||||
guard let url = URL(string: action.url) else {
|
||||
Ghostty.logger.warning("invalid URL for open URL action: \(action.url)")
|
||||
return false
|
||||
}
|
||||
|
||||
switch action.kind {
|
||||
case .text:
|
||||
// Open with the default text editor
|
||||
if let textEditor = NSWorkspace.shared.defaultTextEditor {
|
||||
NSWorkspace.shared.open([url], withApplicationAt: textEditor, configuration: NSWorkspace.OpenConfiguration())
|
||||
return true
|
||||
}
|
||||
|
||||
case .unknown:
|
||||
break
|
||||
}
|
||||
|
||||
// Open with the default application for the URL
|
||||
NSWorkspace.shared.open(url)
|
||||
return true
|
||||
}
|
||||
|
||||
private static func undo(_ app: ghostty_app_t, target: ghostty_target_s) -> Bool {
|
||||
let undoManager: UndoManager?
|
||||
|
@ -73,6 +73,26 @@ extension Ghostty {
|
||||
|
||||
// MARK: Swift Types for C Types
|
||||
|
||||
extension Ghostty {
|
||||
class AllocatedString {
|
||||
private let cString: ghostty_string_s
|
||||
|
||||
init(_ c: ghostty_string_s) {
|
||||
self.cString = c
|
||||
}
|
||||
|
||||
var string: String {
|
||||
guard let ptr = cString.ptr else { return "" }
|
||||
let data = Data(bytes: ptr, count: Int(cString.len))
|
||||
return String(data: data, encoding: .utf8) ?? ""
|
||||
}
|
||||
|
||||
deinit {
|
||||
ghostty_string_free(cString)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Ghostty {
|
||||
enum SetFloatWIndow {
|
||||
case on
|
||||
|
29
macos/Sources/Helpers/Extensions/NSWorkspace+Extension.swift
Normal file
29
macos/Sources/Helpers/Extensions/NSWorkspace+Extension.swift
Normal file
@ -0,0 +1,29 @@
|
||||
import AppKit
|
||||
import UniformTypeIdentifiers
|
||||
|
||||
extension NSWorkspace {
|
||||
/// Returns the URL of the default text editor application.
|
||||
/// - Returns: The URL of the default text editor, or nil if no default text editor is found.
|
||||
var defaultTextEditor: URL? {
|
||||
defaultApplicationURL(forContentType: UTType.plainText.identifier)
|
||||
}
|
||||
|
||||
/// Returns the URL of the default application for opening files with the specified content type.
|
||||
/// - Parameter contentType: The content type identifier (UTI) to find the default application for.
|
||||
/// - Returns: The URL of the default application, or nil if no default application is found.
|
||||
func defaultApplicationURL(forContentType contentType: String) -> URL? {
|
||||
return LSCopyDefaultApplicationURLForContentType(
|
||||
contentType as CFString,
|
||||
.all,
|
||||
nil
|
||||
)?.takeRetainedValue() as? URL
|
||||
}
|
||||
|
||||
/// Returns the URL of the default application for opening files with the specified file extension.
|
||||
/// - Parameter ext: The file extension to find the default application for.
|
||||
/// - Returns: The URL of the default application, or nil if no default application is found.
|
||||
func defaultApplicationURL(forExtension ext: String) -> URL? {
|
||||
guard let uti = UTType(filenameExtension: ext) else { return nil}
|
||||
return defaultApplicationURL(forContentType: uti.identifier)
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-23 16:58+0800\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-05-19 11:34+0300\n"
|
||||
"Last-Translator: Damyan Bogoev <damyan.bogoev@gmail.com>\n"
|
||||
"Language-Team: Bulgarian <dict@ludost.net>\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Оставете празно за възстановяване на заглавието по подразбиране."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Отказ"
|
||||
|
||||
@ -35,22 +36,28 @@ msgid "OK"
|
||||
msgstr "ОК"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Грешки в конфигурацията"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors "
|
||||
"below, and either reload your configuration or ignore these errors."
|
||||
msgstr "Открити са една или повече грешки в конфигурацията. Моля, прегледайте грешките по-долу и или презаредете конфигурацията си, или ги игнорирайте."
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
msgstr ""
|
||||
"Открити са една или повече грешки в конфигурацията. Моля, прегледайте "
|
||||
"грешките по-долу и или презаредете конфигурацията си, или ги игнорирайте."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Игнорирай"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Презареди конфигурацията"
|
||||
|
||||
@ -89,7 +96,7 @@ msgstr "Копирай"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Постави"
|
||||
|
||||
@ -119,7 +126,7 @@ msgstr "Раздел"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:255
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Нов раздел"
|
||||
|
||||
@ -160,7 +167,7 @@ msgid "Terminal Inspector"
|
||||
msgstr "Инспектор на терминала"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1024
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "За Ghostty"
|
||||
|
||||
@ -170,69 +177,64 @@ msgstr "Изход"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Разрешаване на достъп до клипборда"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr "Приложение се опитва да чете от клипборда. Текущото съдържание на клипборда е показано по-долу."
|
||||
msgstr ""
|
||||
"Приложение се опитва да чете от клипборда. Текущото съдържание на клипборда "
|
||||
"е показано по-долу."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Откажи"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Позволи"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr "Приложение се опитва да запише в клипборда. Текущото съдържание на клипборда е показано по-долу."
|
||||
msgstr ""
|
||||
"Приложение се опитва да запише в клипборда. Текущото съдържание на клипборда "
|
||||
"е показано по-долу."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Предупреждение: Потенциално опасно поставяне"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
msgstr "Поставянето на този текст в терминала може да е опасно, тъй като изглежда, че може да бъдат изпълнени някои команди."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:208
|
||||
msgid "Main Menu"
|
||||
msgstr "Главно меню"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:229
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Преглед на отворените раздели"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:256
|
||||
msgid "New Split"
|
||||
msgstr "Ново разделяне"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:319
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Използвате дебъг версия на Ghostty! Производителността ще бъде намалена."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:765
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфигурацията е презаредена"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1005
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Разработчици на Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Инспектор на терминала"
|
||||
msgstr ""
|
||||
"Поставянето на този текст в терминала може да е опасно, тъй като изглежда, "
|
||||
"че може да бъдат изпълнени някои команди."
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
@ -270,6 +272,36 @@ msgstr "Всички терминални сесии в този раздел щ
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Текущият процес в това разделяне ще бъде прекратен."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Копирано в клипборда"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Главно меню"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Преглед на отворените раздели"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "Ново разделяне"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Използвате дебъг версия на Ghostty! Производителността ще бъде намалена."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфигурацията е презаредена"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Разработчици на Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Инспектор на терминала"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-20 08:07+0100\n"
|
||||
"Last-Translator: Francesc Arpi <francesc.arpi@gmail.com>\n"
|
||||
"Language-Team: \n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Deixa en blanc per restaurar el títol per defecte."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Cancel·la"
|
||||
|
||||
@ -35,10 +36,12 @@ msgid "OK"
|
||||
msgstr "D'acord"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Errors de configuració"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -47,12 +50,14 @@ msgstr ""
|
||||
"a continuació i torna a carregar la configuració o ignora aquests errors."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ignora"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Carrega la configuració"
|
||||
|
||||
@ -80,6 +85,10 @@ msgstr "Divideix a l'esquerra"
|
||||
msgid "Split Right"
|
||||
msgstr "Divideix a la dreta"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -87,7 +96,7 @@ msgstr "Copia"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Enganxa"
|
||||
|
||||
@ -117,7 +126,7 @@ msgstr "Pestanya"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nova pestanya"
|
||||
|
||||
@ -145,29 +154,36 @@ msgid "Config"
|
||||
msgstr "Configuració"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Obre la configuració"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Inspector de terminal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Sobre Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Surt"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Autoritza l'accés al porta-retalls"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -177,15 +193,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Denegar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Permet"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -193,11 +224,11 @@ msgstr ""
|
||||
"Una aplicació està intentant escriure al porta-retalls. El contingut actual "
|
||||
"del porta-retalls es mostra a continuació."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Avís: Enganxament potencialment insegur"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -205,33 +236,6 @@ msgstr ""
|
||||
"Enganxar aquest text al terminal pot ser perillós, ja que sembla que es "
|
||||
"podrien executar algunes ordres."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Menú principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Mostra les pestanyes obertes"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Estàs executant una versió de depuració de Ghostty! El rendiment es veurà "
|
||||
"afectat."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "S'ha tornat a carregar la configuració"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desenvolupadors de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Tanca"
|
||||
@ -268,10 +272,37 @@ msgstr "Totes les sessions del terminal en aquesta pestanya es tancaran."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "El procés actualment en execució en aquesta divisió es tancarà."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Copiat al porta-retalls"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menú principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Mostra les pestanyes obertes"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Estàs executant una versió de depuració de Ghostty! El rendiment es veurà "
|
||||
"afectat."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "S'ha tornat a carregar la configuració"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desenvolupadors de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspector de terminal"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-06-28 17:01+0200\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -124,7 +124,7 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:263
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr ""
|
||||
|
||||
@ -165,7 +165,7 @@ msgid "Terminal Inspector"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1036
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr ""
|
||||
|
||||
@ -228,35 +228,6 @@ msgid ""
|
||||
"commands may be executed."
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:238
|
||||
msgid "View Open Tabs"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:264
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:327
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:773
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1017
|
||||
msgid "Ghostty Developers"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr ""
|
||||
@ -296,3 +267,32 @@ msgstr ""
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr ""
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-06 14:57+0100\n"
|
||||
"Last-Translator: Robin <r@rpfaeffle.com>\n"
|
||||
"Language-Team: German <translation-team-de@lists.sourceforge.net>\n"
|
||||
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Leer lassen, um den Standardtitel wiederherzustellen."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Abbrechen"
|
||||
|
||||
@ -36,22 +37,26 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Konfiguration neu laden"
|
||||
|
||||
@ -79,6 +84,10 @@ msgstr "Fenter nach links teilen"
|
||||
msgid "Split Right"
|
||||
msgstr "Fenster nach rechts teilen"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -86,7 +95,7 @@ msgstr "Kopieren"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Einfügen"
|
||||
|
||||
@ -116,7 +125,7 @@ msgstr "Tab"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Neuer Tab"
|
||||
|
||||
@ -144,29 +153,36 @@ msgid "Config"
|
||||
msgstr "Konfiguration"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Konfiguration öffnen"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Terminalinspektor"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Über Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Beenden"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Zugriff auf die Zwischenablage gewähren"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -176,15 +192,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Nicht erlauben"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Erlauben"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -192,11 +223,11 @@ msgstr ""
|
||||
"Eine Anwendung versucht in die Zwischenablage zu schreiben. Der aktuelle "
|
||||
"Inhalt der Zwischenablage wird unten angezeigt."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Achtung: Möglicherweise unsicheres Einfügen"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -204,33 +235,6 @@ msgstr ""
|
||||
"Diesen Text in das Terminal einzufügen könnte möglicherweise gefährlich "
|
||||
"sein. Es scheint, dass Anweisungen ausgeführt werden könnten."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Hauptmenü"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Offene Tabs einblenden"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Du verwendest einen Debug Build von Ghostty! Die Leistung wird reduziert "
|
||||
"sein."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Konfiguration wurde neu geladen"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty-Entwickler"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Schließen"
|
||||
@ -267,10 +271,37 @@ msgstr "Alle Terminalsitzungen in diesem Tab werden beendet."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Der aktuell laufende Prozess in diesem geteilten Fenster wird beendet."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "In die Zwischenablage kopiert"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Hauptmenü"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Offene Tabs einblenden"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Du verwendest einen Debug Build von Ghostty! Die Leistung wird reduziert "
|
||||
"sein."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Konfiguration wurde neu geladen"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty-Entwickler"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr ""
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-23 16:58+0800\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-05-19 20:17-0300\n"
|
||||
"Last-Translator: Alan Moyano <alanmoyano203@gmail.com>\n"
|
||||
"Language-Team: Argentinian <es@tp.org.es>\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Dejar en blanco para restaurar el título predeterminado."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
@ -35,10 +36,12 @@ msgid "OK"
|
||||
msgstr "Aceptar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Errores de configuración"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -47,12 +50,14 @@ msgstr ""
|
||||
"errores a continuación, y recargá tu configuración o ignorá estos errores."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ignorar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Recargar configuración"
|
||||
|
||||
@ -91,7 +96,7 @@ msgstr "Copiar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Pegar"
|
||||
|
||||
@ -121,7 +126,7 @@ msgstr "Pestaña"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:255
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nueva pestaña"
|
||||
|
||||
@ -162,7 +167,7 @@ msgid "Terminal Inspector"
|
||||
msgstr "Inspector de la terminal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1024
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Acerca de Ghostty"
|
||||
|
||||
@ -172,10 +177,13 @@ msgstr "Salir"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Autorizar acceso al portapapeles"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -185,15 +193,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Denegar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Permitir"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -201,11 +224,11 @@ msgstr ""
|
||||
"Una aplicación está intentando escribir en el portapapeles. El contenido "
|
||||
"actual del portapapeles se muestra a continuación."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Advertencia: Pegado potencialmente inseguro"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -213,37 +236,6 @@ msgstr ""
|
||||
"Pegar este texto en la terminal puede ser peligroso ya que parece que "
|
||||
"algunos comandos podrían ejecutarse."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:208
|
||||
msgid "Main Menu"
|
||||
msgstr "Menú principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:229
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Ver pestañas abiertas"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:256
|
||||
msgid "New Split"
|
||||
msgstr "Nueva división"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:319
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Estás ejecutando una versión de depuración de Ghostty. El rendimiento no "
|
||||
"será óptimo."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:765
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Configuración recargada"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1005
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desarrolladores de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspector de la terminal"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
@ -280,6 +272,37 @@ msgstr "Todas las sesiones de terminal en esta pestaña serán terminadas."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "El proceso actualmente en ejecución en esta división será terminado."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Copiado al portapapeles"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menú principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Ver pestañas abiertas"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "Nueva división"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Estás ejecutando una versión de depuración de Ghostty. El rendimiento no "
|
||||
"será óptimo."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Configuración recargada"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desarrolladores de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspector de la terminal"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-28 17:46+0200\n"
|
||||
"Last-Translator: Miguel Peredo <miguelp@quientienemail.com>\n"
|
||||
"Language-Team: Spanish <es@tp.org.es>\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Dejar en blanco para restaurar el título predeterminado."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
@ -35,10 +36,12 @@ msgid "OK"
|
||||
msgstr "Aceptar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Errores de configuración"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -47,12 +50,14 @@ msgstr ""
|
||||
"errores a continuación, y recargue su configuración o ignore estos errores."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ignorar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Recargar configuración"
|
||||
|
||||
@ -80,6 +85,10 @@ msgstr "Dividir a la izquierda"
|
||||
msgid "Split Right"
|
||||
msgstr "Dividir a la derecha"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -87,7 +96,7 @@ msgstr "Copiar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Pegar"
|
||||
|
||||
@ -117,7 +126,7 @@ msgstr "Pestaña"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nueva pestaña"
|
||||
|
||||
@ -145,29 +154,36 @@ msgid "Config"
|
||||
msgstr "Configuración"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Abrir configuración"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Inspector de la terminal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Acerca de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Salir"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Autorizar acceso al portapapeles"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -177,15 +193,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Denegar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Permitir"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -193,11 +224,11 @@ msgstr ""
|
||||
"Una aplicación está intentando escribir en el portapapeles. El contenido "
|
||||
"actual del portapapeles se muestra a continuación."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Advertencia: Pegado potencialmente inseguro"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -205,33 +236,6 @@ msgstr ""
|
||||
"Pegar este texto en la terminal puede ser peligroso ya que parece que "
|
||||
"algunos comandos podrían ejecutarse."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Menú principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Ver pestañas abiertas"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Está ejecutando una versión de depuración de Ghostty. El rendimiento no "
|
||||
"será óptimo."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Configuración recargada"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desarrolladores de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Cerrar"
|
||||
@ -268,10 +272,37 @@ msgstr "Todas las sesiones de terminal en esta pestaña serán terminadas."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "El proceso actualmente en ejecución en esta división será terminado."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Copiado al portapapeles"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menú principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Ver pestañas abiertas"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Está ejecutando una versión de depuración de Ghostty. El rendimiento no "
|
||||
"será óptimo."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Configuración recargada"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desarrolladores de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspector de la terminal"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-22 09:31+0100\n"
|
||||
"Last-Translator: Kirwiisp <swiip__@hotmail.com>\n"
|
||||
"Language-Team: French <traduc@traduc.org>\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Laisser vide pour restaurer le titre par défaut."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Annuler"
|
||||
|
||||
@ -35,10 +36,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Erreurs de configuration"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -48,12 +51,14 @@ msgstr ""
|
||||
"erreurs."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ignorer"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Recharger la configuration"
|
||||
|
||||
@ -81,6 +86,10 @@ msgstr "Panneau à gauche"
|
||||
msgid "Split Right"
|
||||
msgstr "Panneau à droite"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -88,7 +97,7 @@ msgstr "Copier"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Coller"
|
||||
|
||||
@ -118,7 +127,7 @@ msgstr "Onglet"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nouvel onglet"
|
||||
|
||||
@ -146,29 +155,36 @@ msgid "Config"
|
||||
msgstr "Config"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Ouvrir la configuration"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Inspecteur de terminal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "À propos de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Quitter"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Autoriser l'accès au presse-papiers"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -178,15 +194,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Refuser"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Autoriser"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -194,11 +225,11 @@ msgstr ""
|
||||
"Une application essaie d'écrire dans le presse-papiers.Le contenu actuel du "
|
||||
"presse-papiers est affiché ci-dessous."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Attention: Collage potentiellement dangereux"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -206,33 +237,6 @@ msgstr ""
|
||||
"Coller ce texte dans le terminal pourrait être dangereux, il semblerait que "
|
||||
"certaines commandes pourraient être exécutées."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Voir les onglets ouverts"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Vous utilisez une version de débogage de Ghostty ! Les performances seront "
|
||||
"dégradées."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Recharger la configuration"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Les développeurs de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Fermer"
|
||||
@ -269,10 +273,37 @@ msgstr "Toutes les sessions de cet onglet vont être arrêtées."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Le processus en cours dans ce panneau va être arrêté."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Copié dans le presse-papiers"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Voir les onglets ouverts"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Vous utilisez une version de débogage de Ghostty ! Les performances seront "
|
||||
"dégradées."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Recharger la configuration"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Les développeurs de Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspecteur"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-23 16:58+0800\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-06-29 21:15+0100\n"
|
||||
"Last-Translator: Aindriú Mac Giolla Eoin <aindriu80@gmail.com>\n"
|
||||
"Language-Team: Irish <gaeilge-gnulinux@lists.sourceforge.net>\n"
|
||||
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Fág bán chun an teideal réamhshocraithe a athbhunú."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Cealaigh"
|
||||
|
||||
@ -36,10 +37,12 @@ msgid "OK"
|
||||
msgstr "Ceart go leor"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Earráidí cumraíochta"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -48,12 +51,14 @@ msgstr ""
|
||||
"thíos, agus athlódáil do chumraíocht nó déan neamhaird de na hearráidí seo."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Déan neamhaird de"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Athlódáil cumraíocht"
|
||||
|
||||
@ -92,7 +97,7 @@ msgstr "Cóipeáil"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Greamaigh"
|
||||
|
||||
@ -122,7 +127,7 @@ msgstr "Táb"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:255
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Táb nua"
|
||||
|
||||
@ -163,7 +168,7 @@ msgid "Terminal Inspector"
|
||||
msgstr "Cigire teirminéil"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1024
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Maidir le Ghostty"
|
||||
|
||||
@ -173,10 +178,13 @@ msgstr "Scoir"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Údarú rochtain ar an ngearrthaisce"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -186,15 +194,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Diúltaigh"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Ceadaigh"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -202,11 +225,11 @@ msgstr ""
|
||||
"Tá feidhmchlár ag iarraidh scríobh chuig an ngearrthaisce. Taispeántar ábhar "
|
||||
"reatha an ghearrthaisce thíos."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Rabhadh: Greamaigh a d'fhéadfadh a bheith neamhshábháilte"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -214,36 +237,6 @@ msgstr ""
|
||||
"D’fhéadfadh sé a bheith contúirteach an téacs seo a ghreamú isteach sa "
|
||||
"teirminéal, toisc go d'fhéadfadh roinnt orduithe a fhorghníomhú."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:208
|
||||
msgid "Main Menu"
|
||||
msgstr "Príomh-Roghchlár"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:229
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Féach ar na táib oscailte"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:256
|
||||
msgid "New Split"
|
||||
msgstr "Scoilt nua"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:319
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Tá leagan dífhabhtaithe de Ghostty á rith agat! Laghdófar an fheidhmíocht."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:765
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Tá an chumraíocht athlódáilte"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1005
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Forbróirí Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Cigire teirminéil"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Dún"
|
||||
@ -281,6 +274,36 @@ msgid "The currently running process in this split will be terminated."
|
||||
msgstr ""
|
||||
"Cuirfear deireadh leis an bpróiseas atá ar siúl faoi láthair sa scoilt seo."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Cóipeáilte chuig an ghearrthaisce"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Príomh-Roghchlár"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Féach ar na táib oscailte"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "Scoilt nua"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Tá leagan dífhabhtaithe de Ghostty á rith agat! Laghdófar an fheidhmíocht."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Tá an chumraíocht athlódáilte"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Forbróirí Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Cigire teirminéil"
|
||||
|
304
po/he_IL.UTF-8.po
Normal file
304
po/he_IL.UTF-8.po
Normal file
@ -0,0 +1,304 @@
|
||||
# Hebrew translations for com.mitchellh.ghostty.
|
||||
# Copyright (C) 2025 Mitchell Hashimoto
|
||||
# This file is distributed under the same license as the com.mitchellh.ghostty package.
|
||||
# Sl (Shahaf Levi), Sl's Repository Ltd <ghostty@slsrepo.com>, 2025.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-13 00:00+0000\n"
|
||||
"Last-Translator: Sl (Shahaf Levi), Sl's Repository Ltd <ghostty@slsrepo."
|
||||
"com>\n"
|
||||
"Language-Team: Hebrew <he_IL@lists.sourceforge.net>\n"
|
||||
"Language: he\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:5
|
||||
msgid "Change Terminal Title"
|
||||
msgstr "שינוי כותרת המסוף"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:6
|
||||
msgid "Leave blank to restore the default title."
|
||||
msgstr "השאר/י ריק כדי לשחזר את כותרת ברירת המחדל."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "ביטול"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:10
|
||||
msgid "OK"
|
||||
msgstr "אישור"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "שגיאות בהגדרות"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
msgstr ""
|
||||
"נמצאו אחת או יותר שגיאות בהגדרות. אנא בדוק/י את השגיאות המופיעות מטה ולאחר "
|
||||
"מכן טען/י את ההגדרות מחדש או התעלם/י מהשגיאות."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "התעלמות"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "טעינה מחדש של ההגדרות"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
|
||||
msgid "Split Up"
|
||||
msgstr "פיצול למעלה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
|
||||
msgid "Split Down"
|
||||
msgstr "פיצול למטה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
|
||||
msgid "Split Left"
|
||||
msgstr "פיצול שמאלה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
|
||||
msgid "Split Right"
|
||||
msgstr "פיצול ימינה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr "הרץ/י פקודה…"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
msgstr "העתקה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "הדבקה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:18
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:73
|
||||
msgid "Clear"
|
||||
msgstr "ניקוי"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:23
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:78
|
||||
msgid "Reset"
|
||||
msgstr "איפוס"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:30
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:42
|
||||
msgid "Split"
|
||||
msgstr "פיצול"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:33
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:45
|
||||
msgid "Change Title…"
|
||||
msgstr "שינוי כותרת…"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
|
||||
msgid "Tab"
|
||||
msgstr "כרטיסייה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "כרטיסייה חדשה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:67
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:35
|
||||
msgid "Close Tab"
|
||||
msgstr "סגור/י כרטיסייה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:73
|
||||
msgid "Window"
|
||||
msgstr "חלון"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:76
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:18
|
||||
msgid "New Window"
|
||||
msgstr "חלון חדש"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:81
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:23
|
||||
msgid "Close Window"
|
||||
msgstr "סגור/י חלון"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:89
|
||||
msgid "Config"
|
||||
msgstr "הגדרות"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "פתיחת ההגדרות"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr "לוח פקודות"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "בודק המסוף"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "אודות Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "יציאה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "אשר/י גישה ללוח ההעתקה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr "יש אפליקציה שמנסה לקרוא מלוח ההעתקה. התוכן הנוכחי של הלוח מופיע למטה."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "דחייה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "אישור"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr "זכור/י את הבחירה עבור פיצול זה"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr "טען/י את ההגדרות מחדש כדי להציג את הבקשה הזו שוב"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr ""
|
||||
"יש אפליקציה שמנסה לכתוב לתוך לוח ההעתקה. התוכן הנוכחי של הלוח מופיע למטה."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "אזהרה: ההדבקה עלולה להיות מסוכנת"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
msgstr ""
|
||||
"הדבקת טקסט זה במסוף עלולה להיות מסוכנת, מכיוון שככל הנראה היא תוביל להרצה של "
|
||||
"פקודות מסוימות."
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "סגירה"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:87
|
||||
msgid "Quit Ghostty?"
|
||||
msgstr "לצאת מGhostty?"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:88
|
||||
msgid "Close Window?"
|
||||
msgstr "לסגור את החלון?"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:89
|
||||
msgid "Close Tab?"
|
||||
msgstr "לסגור את הכרטיסייה?"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:90
|
||||
msgid "Close Split?"
|
||||
msgstr "לסגור את הפיצול?"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:96
|
||||
msgid "All terminal sessions will be terminated."
|
||||
msgstr "כל הפעלות המסוף יסתיימו."
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:97
|
||||
msgid "All terminal sessions in this window will be terminated."
|
||||
msgstr "כל הפעלות המסוף בחלון זה יסתיימו."
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:98
|
||||
msgid "All terminal sessions in this tab will be terminated."
|
||||
msgstr "כל הפעלות המסוף בכרטיסייה זו יסתיימו."
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:99
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "התהליך שרץ כרגע בפיצול זה יסתיים."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "הועתק ללוח ההעתקה"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "תפריט ראשי"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "הצג/י כרטיסיות פתוחות"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "פיצול חדש"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ את/ה מריץ/ה גרסת ניפוי שגיאות של Ghostty! הביצועים יהיו ירודים."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "ההגדרות הוטענו מחדש"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "המפתחים של Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: בודק המסוף"
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-20 15:19+0700\n"
|
||||
"Last-Translator: Satrio Bayu Aji <halosatrio@gmail.com>\n"
|
||||
"Language-Team: Indonesian <translation-team-id@lists.sourceforge.net>\n"
|
||||
@ -25,7 +25,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Biarkan kosong untuk mengembalikan judul bawaan."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Batal"
|
||||
|
||||
@ -34,10 +35,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Kesalahan konfigurasi"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -46,12 +49,14 @@ msgstr ""
|
||||
"bawah ini, dan muat ulang konfigurasi anda atau abaikan kesalahan ini."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Abaikan"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Muat ulang konfigurasi"
|
||||
|
||||
@ -79,6 +84,10 @@ msgstr "Belah kiri"
|
||||
msgid "Split Right"
|
||||
msgstr "Belah kanan"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -86,7 +95,7 @@ msgstr "Salin"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Tempel"
|
||||
|
||||
@ -116,7 +125,7 @@ msgstr "Tab"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Tab baru"
|
||||
|
||||
@ -144,29 +153,36 @@ msgid "Config"
|
||||
msgstr "Konfigurasi"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Buka konfigurasi"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Inspektur terminal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Tentang Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Keluar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Mengesahkan akses papan klip"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -176,15 +192,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Menyangkal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Izinkan"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -192,11 +223,11 @@ msgstr ""
|
||||
"Aplikasi sedang mencoba menulis ke papan klip. Isi papan klip saat ini "
|
||||
"ditampilkan di bawah ini."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Peringatan: Tempelan yang berpotensi tidak aman"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -204,32 +235,6 @@ msgstr ""
|
||||
"Menempelkan teks ini ke terminal mungkin berbahaya karena sepertinya "
|
||||
"beberapa perintah mungkin dijalankan."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu utama"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Lihat tab terbuka"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Anda sedang menjalankan versi debug dari Ghostty! Performa akan menurun."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Memuat ulang konfigurasi"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Pengembang Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Tutup"
|
||||
@ -266,10 +271,36 @@ msgstr "Semua sesi terminal di tab ini akan diakhiri."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Proses yang sedang berjalan dalam belahan ini akan diakhiri."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Disalin ke papan klip"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu utama"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Lihat tab terbuka"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Anda sedang menjalankan versi debug dari Ghostty! Performa akan menurun."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Memuat ulang konfigurasi"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Pengembang Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspektur terminal"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-21 00:08+0900\n"
|
||||
"Last-Translator: Lon Sagisawa <lon@sagisawa.me>\n"
|
||||
"Language-Team: Japanese\n"
|
||||
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "空白にした場合、デフォルトのタイトルを使用します。"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "キャンセル"
|
||||
|
||||
@ -36,10 +37,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "設定ファイルにエラーがあります"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -48,12 +51,14 @@ msgstr ""
|
||||
"みをするか、無視してください。"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "無視"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "設定ファイルの再読み込み"
|
||||
|
||||
@ -81,6 +86,10 @@ msgstr "左に分割"
|
||||
msgid "Split Right"
|
||||
msgstr "右に分割"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -88,7 +97,7 @@ msgstr "コピー"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "貼り付け"
|
||||
|
||||
@ -118,7 +127,7 @@ msgstr "タブ"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "新しいタブ"
|
||||
|
||||
@ -146,29 +155,36 @@ msgid "Config"
|
||||
msgstr "設定"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "設定ファイルを開く"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "端末インスペクター"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Ghostty について"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "終了"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "クリップボードへのアクセスを承認"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -178,15 +194,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "拒否"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "許可"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -194,11 +225,11 @@ msgstr ""
|
||||
"アプリケーションがクリップボードに書き込もうとしています。現在のクリップボー"
|
||||
"ドの内容は以下の通りです。"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "警告: 危険な可能性のある貼り付け"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -206,32 +237,6 @@ msgstr ""
|
||||
"このテキストには実行可能なコマンドが含まれており、ターミナルに貼り付けるのは"
|
||||
"危険な可能性があります。"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "メインメニュー"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "開いているすべてのタブを表示"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Ghostty のデバッグビルドを実行しています! パフォーマンスが低下しています。"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "設定を再読み込みしました"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty 開発者"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "閉じる"
|
||||
@ -268,10 +273,36 @@ msgstr "タブ内のすべてのターミナルセッションが終了します
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "分割ウィンドウ内のすべてのプロセスが終了します。"
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "クリップボードにコピーしました"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "メインメニュー"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "開いているすべてのタブを表示"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Ghostty のデバッグビルドを実行しています! パフォーマンスが低下しています。"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "設定を再読み込みしました"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty 開発者"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: 端末インスペクター"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-03-19 08:54-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-31 03:08+0200\n"
|
||||
"Last-Translator: Ruben Engelbrecht <hey@rme.gg>\n"
|
||||
"Language-Team: Korean <translation-team-ko@googlegroups.com>\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "제목란을 비워 두면 기본값으로 복원됩니다."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "취소"
|
||||
|
||||
@ -35,25 +36,59 @@ msgid "OK"
|
||||
msgstr "확인"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "설정 오류"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
msgstr "설정에 하나 이상의 문제가 발견되었습니다. 아래 오류(를)들을 확인한 후 설정을 다시 불러오거나 무시하세요."
|
||||
msgstr ""
|
||||
"설정에 하나 이상의 문제가 발견되었습니다. 아래 오류(를)들을 확인한 후 설정을 "
|
||||
"다시 불러오거나 무시하세요."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "무시"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "설정 값 다시 불러오기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
|
||||
msgid "Split Up"
|
||||
msgstr "위로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
|
||||
msgid "Split Down"
|
||||
msgstr "아래로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:16
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
|
||||
msgid "Split Left"
|
||||
msgstr "왼쪽으로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-headerbar-split_menu.blp:21
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
|
||||
msgid "Split Right"
|
||||
msgstr "오른쪽으로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -61,7 +96,7 @@ msgstr "복사"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "붙여넣기"
|
||||
|
||||
@ -85,33 +120,13 @@ msgstr "나누기"
|
||||
msgid "Change Title…"
|
||||
msgstr "제목 변경…"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:38
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:50
|
||||
msgid "Split Up"
|
||||
msgstr "위로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:43
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:55
|
||||
msgid "Split Down"
|
||||
msgstr "아래로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:48
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:60
|
||||
msgid "Split Left"
|
||||
msgstr "왼쪽으로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:53
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:65
|
||||
msgid "Split Right"
|
||||
msgstr "오른쪽으로 창 나누기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:59
|
||||
msgid "Tab"
|
||||
msgstr "탭"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:246
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "새 탭"
|
||||
|
||||
@ -139,67 +154,87 @@ msgid "Config"
|
||||
msgstr "설정"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "설정 열기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "터미널 인스펙터"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:960
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Ghostty 정보"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "종료"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "클립보드 액세스 권한 부여"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr "응용 프로그램이 클립보드에서 읽기를 시도하고 있습니다. 현재 클립보드 내용은 아래와 같습니다."
|
||||
msgstr ""
|
||||
"응용 프로그램이 클립보드에서 읽기를 시도하고 있습니다. 현재 클립보드 내용은 "
|
||||
"아래와 같습니다."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "거부"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "허용"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr "응용 프로그램이 클립보드에 쓰기를 시도하고 있습니다. 현재 클립보드 내용은 아래와 같습니다."
|
||||
msgstr ""
|
||||
"응용 프로그램이 클립보드에 쓰기를 시도하고 있습니다. 현재 클립보드 내용은 아"
|
||||
"래와 같습니다."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "경고: 잠재적으로 안전하지 않은 붙여넣기"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
msgstr "이 텍스트를 터미널에 붙여넣는 것은 위험할 수 있습니다. 일부 명령이 실행될 수 있는 것으로 보입니다."
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: 터미널 인스펙터"
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "클립보드에 복사됨"
|
||||
msgstr ""
|
||||
"이 텍스트를 터미널에 붙여넣는 것은 위험할 수 있습니다. 일부 명령이 실행될 수 "
|
||||
"있는 것으로 보입니다."
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
@ -237,23 +272,36 @@ msgstr "이 탭의 모든 터미널 세션이 종료됩니다."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "이 분할에서 현재 실행 중인 프로세스가 종료됩니다."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:200
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "클립보드에 복사됨"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "메인 메뉴"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:221
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "열린 탭 보기"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:295
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
#, fuzzy
|
||||
msgid "New Split"
|
||||
msgstr "나누기"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Ghostty 디버그 빌드로 실행 중입니다! 성능이 저하됩니다."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:725
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "설정값을 다시 불러왔습니다"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:941
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty 개발자들"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: 터미널 인스펙터"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-23 14:17+0100\n"
|
||||
"Last-Translator: Andrej Daskalov <andrej.daskalov@gmail.com>\n"
|
||||
"Language-Team: Macedonian\n"
|
||||
@ -25,7 +25,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Оставете празно за враќање на стандарсниот наслов."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Откажи"
|
||||
|
||||
@ -34,10 +35,12 @@ msgid "OK"
|
||||
msgstr "Во ред"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Грешки во конфигурацијата"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -47,12 +50,14 @@ msgstr ""
|
||||
"овие грешки."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Игнорирај"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Одново вчитај конфигурација"
|
||||
|
||||
@ -80,6 +85,10 @@ msgstr "Подели налево"
|
||||
msgid "Split Right"
|
||||
msgstr "Подели надесно"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -87,7 +96,7 @@ msgstr "Копирај"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Вметни"
|
||||
|
||||
@ -117,7 +126,7 @@ msgstr "Јазиче"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Ново јазиче"
|
||||
|
||||
@ -145,29 +154,36 @@ msgid "Config"
|
||||
msgstr "Конфигурација"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Отвори конфигурација"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Инспектор на терминал"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "За Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Излез"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Авторизирај пристап до привремена меморија"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -177,15 +193,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Одбиј"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Дозволи"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -193,11 +224,11 @@ msgstr ""
|
||||
"Апликација се обидува да запише во привремената меморија. Содржината е "
|
||||
"прикажана подолу."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Предупредување: Потенцијално небезбедно вметнување"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -205,32 +236,6 @@ msgstr ""
|
||||
"Вметнувањето на овој текст во терминалот може да биде опасно, бидејќи "
|
||||
"изгледа како да ќе се извршат одредени команди."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Главно мени"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Прегледај отворени јазичиња"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Извршувате дебаг верзија на Ghostty! Перформансите ќе бидат намалени."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфигурацијата е одново вчитана"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Развивачи на Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Затвори"
|
||||
@ -267,10 +272,36 @@ msgstr "Сите сесии во ова јазиче ќе бидат преки
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Процесот кој моментално се извршува во оваа поделба ќе биде прекинат."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Копирано во привремена меморија"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Главно мени"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Прегледај отворени јазичиња"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Извршувате дебаг верзија на Ghostty! Перформансите ќе бидат намалени."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфигурацијата е одново вчитана"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Развивачи на Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Инспектор на терминал"
|
||||
|
@ -10,7 +10,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-04-14 16:25+0200\n"
|
||||
"Last-Translator: cryptocode <cryptocode@zolo.io>\n"
|
||||
"Language-Team: Norwegian Bokmal <l10n-no@lister.huftis.org>\n"
|
||||
@ -29,7 +29,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Blank verdi gjenoppretter standardtittelen."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Avbryt"
|
||||
|
||||
@ -38,10 +39,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Konfigurasjonsfeil"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -50,12 +53,14 @@ msgstr ""
|
||||
"under, og enten last konfigurasjonen din på nytt eller ignorer disse feilene."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ignorer"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Last konfigurasjon på nytt"
|
||||
|
||||
@ -83,6 +88,10 @@ msgstr "Del til venstre"
|
||||
msgid "Split Right"
|
||||
msgstr "Del til høyre"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -90,7 +99,7 @@ msgstr "Kopier"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Lim inn"
|
||||
|
||||
@ -120,7 +129,7 @@ msgstr "Fane"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Ny fane"
|
||||
|
||||
@ -148,29 +157,36 @@ msgid "Config"
|
||||
msgstr "Konfigurasjon"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Åpne konfigurasjon"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Terminalinspektør"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Om Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Avslutt"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Gi tilgang til utklippstavlen"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -180,15 +196,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Avslå"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Tillat"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -196,11 +227,11 @@ msgstr ""
|
||||
"En applikasjon forsøker å skrive til utklippstavlen. Gjeldende "
|
||||
"utklippstavleinnhold er vist nedenfor."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Adarsel: Lim inn kan være utrygt"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -208,31 +239,6 @@ msgstr ""
|
||||
"Det ser ut som at kommandoer vil bli kjørt hvis du limer inn dette, vurder "
|
||||
"om du mener det er trygt."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Hovedmeny"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Se åpne faner"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr "Del opp vindu"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Du kjører et debug-bygg av Ghostty. Debug-bygg har redusert ytelse."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Konfigurasjonen ble lastet på nytt"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty-utviklere"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Lukk"
|
||||
@ -269,10 +275,35 @@ msgstr "Alle terminaløkter i denne fanen vil bli avsluttet."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Den kjørende prosessen for denne splitten vil bli avsluttet."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Kopiert til utklippstavlen"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Hovedmeny"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Se åpne faner"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "Del opp vindu"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Du kjører et debug-bygg av Ghostty. Debug-bygg har redusert ytelse."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Konfigurasjonen ble lastet på nytt"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty-utviklere"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Terminalinspektør"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-24 15:00+0100\n"
|
||||
"Last-Translator: Nico Geesink <geesinknico@gmail.com>\n"
|
||||
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Laat leeg om de standaard titel te herstellen."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Annuleren"
|
||||
|
||||
@ -35,10 +36,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Configuratiefouten"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -47,12 +50,14 @@ msgstr ""
|
||||
"fouten en herlaad je configuratie of negeer deze fouten."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Negeer"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Herlaad configuratie"
|
||||
|
||||
@ -80,6 +85,10 @@ msgstr "Splits naar links"
|
||||
msgid "Split Right"
|
||||
msgstr "Splits naar rechts"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -87,7 +96,7 @@ msgstr "Kopiëren"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Plakken"
|
||||
|
||||
@ -117,7 +126,7 @@ msgstr "Tabblad"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nieuw tabblad"
|
||||
|
||||
@ -145,29 +154,36 @@ msgid "Config"
|
||||
msgstr "Configuratie"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Open configuratie"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Terminal inspecteur"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Over Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Afsluiten"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Verleen toegang tot klembord"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -177,15 +193,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Weigeren"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Toestaan"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -193,11 +224,11 @@ msgstr ""
|
||||
"Een applicatie probeert de inhoud van het klembord te wijzigen. De huidige "
|
||||
"inhoud van het klembord wordt hieronder weergegeven."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Waarschuwing: mogelijk onveilige plakactie"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -205,33 +236,6 @@ msgstr ""
|
||||
"Het plakken van deze tekst in de terminal is mogelijk gevaarlijk, omdat het "
|
||||
"lijkt op een commando dat uitgevoerd kan worden."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Hoofdmenu"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Open tabbladen bekijken"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Je draait een debug versie van Ghostty! Prestaties zullen minder zijn dan "
|
||||
"normaal."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "De configuratie is herladen"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty ontwikkelaars"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Afsluiten"
|
||||
@ -269,10 +273,37 @@ msgid "The currently running process in this split will be terminated."
|
||||
msgstr ""
|
||||
"Alle processen die nu draaien in deze splitsing zullen worden beëindigd."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Gekopieerd naar klembord"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Hoofdmenu"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Open tabbladen bekijken"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Je draait een debug versie van Ghostty! Prestaties zullen minder zijn dan "
|
||||
"normaal."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "De configuratie is herladen"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty ontwikkelaars"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: terminal inspecteur"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-17 12:15+0100\n"
|
||||
"Last-Translator: Bartosz Sokorski <b.sokorski@gmail.com>\n"
|
||||
"Language-Team: Polish <translation-team-pl@lists.sourceforge.net>\n"
|
||||
@ -28,7 +28,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Pozostaw puste by przywrócić domyślny tytuł."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Anuluj"
|
||||
|
||||
@ -37,10 +38,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Błędy konfiguracji"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -49,12 +52,14 @@ msgstr ""
|
||||
"poniżej i przeładuj konfigurację lub zignoruj je."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Zignoruj"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Przeładuj konfigurację"
|
||||
|
||||
@ -82,6 +87,10 @@ msgstr "Podziel w lewo"
|
||||
msgid "Split Right"
|
||||
msgstr "Podziel w prawo"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -89,7 +98,7 @@ msgstr "Kopiuj"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Wklej"
|
||||
|
||||
@ -119,7 +128,7 @@ msgstr "Karta"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nowa karta"
|
||||
|
||||
@ -147,29 +156,36 @@ msgid "Config"
|
||||
msgstr "Konfiguracja"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Otwórz konfigurację"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Inspektor terminala"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "O Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Zamknij"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Udziel dostępu do schowka"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -179,15 +195,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Odmów"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Zezwól"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -195,11 +226,11 @@ msgstr ""
|
||||
"Aplikacja próbuje zapisać do schowka. Obecna zawartość schowka pokazana "
|
||||
"poniżej."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Uwaga: potencjalnie niebezpieczne wklejenie ze schowka"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -207,31 +238,6 @@ msgstr ""
|
||||
"Wklejenie tego tekstu do terminala może być niebezpieczne, ponieważ może "
|
||||
"spowodować wykonanie komend."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu główne"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Zobacz otwarte karty"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Używasz wersji Ghostty do debugowania! Wydajność będzie obniżona."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Przeładowano konfigurację"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Twórcy Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Zamknij"
|
||||
@ -268,10 +274,35 @@ msgstr "Wszystkie sesje terminala w obecnej karcie zostaną zakończone."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Wszyskie trwające procesy w obecnym podziale zostaną zakończone."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Skopiowano do schowka"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu główne"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Zobacz otwarte karty"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Używasz wersji Ghostty do debugowania! Wydajność będzie obniżona."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Przeładowano konfigurację"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Twórcy Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Inspektor terminala Ghostty"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-06-20 10:19-0300\n"
|
||||
"Last-Translator: Mário Victor Ribeiro Silva <mariovictorrs@gmail.com>\n"
|
||||
"Language-Team: Brazilian Portuguese <ldpbr-translation@lists.sourceforge."
|
||||
@ -28,7 +28,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Deixe em branco para restaurar o título original."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Cancelar"
|
||||
|
||||
@ -37,10 +38,12 @@ msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Erros de configuração"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -49,12 +52,14 @@ msgstr ""
|
||||
"abaixo, e ou recarregue sua configuração, ou ignore esses erros."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ignorar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Recarregar configuração"
|
||||
|
||||
@ -82,6 +87,10 @@ msgstr "Dividir à esquerda"
|
||||
msgid "Split Right"
|
||||
msgstr "Dividir à direita"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -89,7 +98,7 @@ msgstr "Copiar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Colar"
|
||||
|
||||
@ -119,7 +128,7 @@ msgstr "Aba"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Nova aba"
|
||||
|
||||
@ -147,29 +156,36 @@ msgid "Config"
|
||||
msgstr "Configurar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Abrir configuração"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Inspetor de terminal"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Sobre o Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Sair"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Autorizar acesso à área de transferência"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -179,15 +195,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Negar"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Permitir"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -195,11 +226,11 @@ msgstr ""
|
||||
"Uma aplicação está tentando escrever na área de transferência. O conteúdo "
|
||||
"atual da área de transferência está aparecendo abaixo."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Aviso: Conteúdo potencialmente inseguro"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -207,32 +238,6 @@ msgstr ""
|
||||
"Colar esse texto em um terminal pode ser perigoso, pois parece que alguns "
|
||||
"comandos podem ser executados."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu Principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Visualizar abas abertas"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr "Nova divisão"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Você está rodando uma build de debug do Ghostty! O desempenho será afetado."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Configuração recarregada"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desenvolvedores Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Fechar"
|
||||
@ -269,10 +274,36 @@ msgstr "Todas as sessões de terminal nessa aba serão finalizadas."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "O processo atual rodando nessa divisão será finalizado."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Copiado para a área de transferência"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu Principal"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Visualizar abas abertas"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "Nova divisão"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Você está rodando uma build de debug do Ghostty! O desempenho será afetado."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Configuração recarregada"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Desenvolvedores Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Inspetor de terminal"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-24 00:01+0500\n"
|
||||
"Last-Translator: blackzeshi <sergey_zhuzhgov@mail.ru>\n"
|
||||
"Language-Team: Russian <gnu@d07.ru>\n"
|
||||
@ -28,7 +28,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Оставьте пустым, чтобы восстановить исходный заголовок."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Отмена"
|
||||
|
||||
@ -37,10 +38,12 @@ msgid "OK"
|
||||
msgstr "ОК"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Ошибки конфигурации"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -49,12 +52,14 @@ msgstr ""
|
||||
"конфигурацию, либо проигнорируйте ошибки."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Игнорировать"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Обновить конфигурацию"
|
||||
|
||||
@ -82,6 +87,10 @@ msgstr "Сплит влево"
|
||||
msgid "Split Right"
|
||||
msgstr "Сплит вправо"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -89,7 +98,7 @@ msgstr "Копировать"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Вставить"
|
||||
|
||||
@ -119,7 +128,7 @@ msgstr "Вкладка"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Новая вкладка"
|
||||
|
||||
@ -147,29 +156,36 @@ msgid "Config"
|
||||
msgstr "Конфигурация"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Открыть конфигурационный файл"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Инспектор терминала"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "О Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Выход"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Разрешить доступ к буферу обмена"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -179,26 +195,41 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Отклонить"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Разрешить"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
msgstr ""
|
||||
"Приложение пытается записать данные в буфер обмена. Эти данные показаны ниже."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Внимание! Вставляемые данные могут нанести вред вашей системе"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -206,33 +237,6 @@ msgstr ""
|
||||
"Вставка этого текста в терминал может быть опасной. Это выглядит как "
|
||||
"команды, которые могут быть исполнены."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Главное меню"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Просмотреть открытые вкладки"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Вы запустили отладочную сборку Ghostty! Это может влиять на "
|
||||
"производительность."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфигурация была обновлена"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Разработчики Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Закрыть"
|
||||
@ -269,10 +273,37 @@ msgstr "Все сессии терминала в этой вкладке буд
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Процесс, работающий в этой сплит-области, будет остановлен."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Скопировано в буфер обмена"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Главное меню"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Просмотреть открытые вкладки"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Вы запустили отладочную сборку Ghostty! Это может влиять на "
|
||||
"производительность."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфигурация была обновлена"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Разработчики Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: инспектор терминала"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-24 22:01+0300\n"
|
||||
"Last-Translator: Emir SARI <emir_sari@icloud.com>\n"
|
||||
"Language-Team: Turkish\n"
|
||||
@ -26,7 +26,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Öntanımlı başlığı geri yüklemek için boş bırakın."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "İptal"
|
||||
|
||||
@ -35,10 +36,12 @@ msgid "OK"
|
||||
msgstr "Tamam"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Yapılandırma Hataları"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -48,12 +51,14 @@ msgstr ""
|
||||
"hataları yok sayın."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Yok Say"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Yapılandırmayı Yeniden Yükle"
|
||||
|
||||
@ -81,6 +86,10 @@ msgstr "Sola Doğru Böl"
|
||||
msgid "Split Right"
|
||||
msgstr "Sağa Doğru Böl"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -88,7 +97,7 @@ msgstr "Kopyala"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Yapıştır"
|
||||
|
||||
@ -118,7 +127,7 @@ msgstr "Sekme"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Yeni Sekme"
|
||||
|
||||
@ -146,29 +155,36 @@ msgid "Config"
|
||||
msgstr "Yapılandırma"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Yapılandırmayı Aç"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Uçbirim Denetçisi"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Ghostty Hakkında"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Çık"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Pano Erişimine İzin Ver"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -178,15 +194,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Reddet"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "İzin Ver"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -194,11 +225,11 @@ msgstr ""
|
||||
"Bir uygulama panoya yazmaya çalışıyor. Geçerli pano içeriği aşağıda "
|
||||
"gösterilmektedir."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Uyarı: Tehlikeli Olabilecek Yapıştırma"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -206,33 +237,6 @@ msgstr ""
|
||||
"Bu metni uçbirime yapıştırmak tehlikeli olabilir; çünkü bir komut "
|
||||
"yürütülebilecekmiş gibi duruyor."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Ana Menü"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Açık Sekmeleri Görüntüle"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr "Yeni Bölme"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Ghostty’nin hata ayıklama amaçlı yapılmış bir sürümünü kullanıyorsunuz! "
|
||||
"Başarım normale göre daha düşük olacaktır."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Yapılandırma yeniden yüklendi"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty Geliştiricileri"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Kapat"
|
||||
@ -269,10 +273,37 @@ msgstr "Bu sekmedeki tüm uçbirim oturumları sonlandırılacaktır."
|
||||
msgid "The currently running process in this split will be terminated."
|
||||
msgstr "Bu bölmedeki şu anda çalışan süreç sonlandırılacaktır."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Panoya kopyalandı"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Ana Menü"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Açık Sekmeleri Görüntüle"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "Yeni Bölme"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Ghostty’nin hata ayıklama amaçlı yapılmış bir sürümünü kullanıyorsunuz! "
|
||||
"Başarım normale göre daha düşük olacaktır."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Yapılandırma yeniden yüklendi"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty Geliştiricileri"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Uçbirim Denetçisi"
|
||||
|
@ -7,7 +7,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-04-22 08:57-0700\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-03-16 20:16+0200\n"
|
||||
"Last-Translator: Danylo Zalizchuk <danilmail0110@gmail.com>\n"
|
||||
"Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n"
|
||||
@ -27,7 +27,8 @@ msgid "Leave blank to restore the default title."
|
||||
msgstr "Залиште порожнім, щоб відновити назву за замовчуванням."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/prompt-title-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/CloseDialog.zig:44
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:10 src/apprt/gtk/ui/1.2/ccw-paste.blp:10
|
||||
#: src/apprt/gtk/CloseDialog.zig:44
|
||||
msgid "Cancel"
|
||||
msgstr "Відмінити"
|
||||
|
||||
@ -36,10 +37,12 @@ msgid "OK"
|
||||
msgstr "ОК"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:5
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:5
|
||||
msgid "Configuration Errors"
|
||||
msgstr "Помилки конфігурації"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:6
|
||||
msgid ""
|
||||
"One or more configuration errors were found. Please review the errors below, "
|
||||
"and either reload your configuration or ignore these errors."
|
||||
@ -49,12 +52,14 @@ msgstr ""
|
||||
"ці помилки."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:9
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:9
|
||||
msgid "Ignore"
|
||||
msgstr "Ігнорувати"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/config-errors-dialog.blp:10
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:97
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:100
|
||||
#: src/apprt/gtk/ui/1.2/config-errors-dialog.blp:10
|
||||
msgid "Reload Configuration"
|
||||
msgstr "Перезавантажити конфігурацію"
|
||||
|
||||
@ -82,6 +87,10 @@ msgstr "Розділити панель ліворуч"
|
||||
msgid "Split Right"
|
||||
msgstr "Розділити панель праворуч"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/command-palette.blp:16
|
||||
msgid "Execute a command…"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:6
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:6
|
||||
msgid "Copy"
|
||||
@ -89,7 +98,7 @@ msgstr "Скопіювати"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:11 src/apprt/gtk/ui/1.2/ccw-paste.blp:11
|
||||
msgid "Paste"
|
||||
msgstr "Вставити"
|
||||
|
||||
@ -119,7 +128,7 @@ msgstr "Вкладка"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:248
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "Нова вкладка"
|
||||
|
||||
@ -147,29 +156,36 @@ msgid "Config"
|
||||
msgstr "Конфігурація"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:92
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:95
|
||||
msgid "Open Configuration"
|
||||
msgstr "Відкрити конфігурацію"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:85
|
||||
msgid "Command Palette"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:90
|
||||
msgid "Terminal Inspector"
|
||||
msgstr "Інспектор терміналу"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:102
|
||||
#: src/apprt/gtk/Window.zig:1003
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "Про Ghostty"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:112
|
||||
msgid "Quit"
|
||||
msgstr "Завершити"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:6
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:6
|
||||
msgid "Authorize Clipboard Access"
|
||||
msgstr "Дозволити доступ до буфера обміну"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to read from the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -179,15 +195,30 @@ msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:10
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:10
|
||||
msgid "Deny"
|
||||
msgstr "Відхилити"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-read.blp:11
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:11
|
||||
msgid "Allow"
|
||||
msgstr "Дозволити"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:81
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:77
|
||||
msgid "Remember choice for this split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-read.blp:82
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:78
|
||||
msgid "Reload configuration to show this prompt again"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-osc-52-write.blp:7
|
||||
#: src/apprt/gtk/ui/1.2/ccw-osc-52-write.blp:7
|
||||
msgid ""
|
||||
"An application is attempting to write to the clipboard. The current "
|
||||
"clipboard contents are shown below."
|
||||
@ -195,11 +226,11 @@ msgstr ""
|
||||
"Програма намагається записати дані до буфера обміну. Нижче показано поточний "
|
||||
"вміст буфера обміну."
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:6 src/apprt/gtk/ui/1.2/ccw-paste.blp:6
|
||||
msgid "Warning: Potentially Unsafe Paste"
|
||||
msgstr "Увага: потенційно небезпечна вставка"
|
||||
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7
|
||||
#: src/apprt/gtk/ui/1.5/ccw-paste.blp:7 src/apprt/gtk/ui/1.2/ccw-paste.blp:7
|
||||
msgid ""
|
||||
"Pasting this text into the terminal may be dangerous as it looks like some "
|
||||
"commands may be executed."
|
||||
@ -207,32 +238,6 @@ msgstr ""
|
||||
"Вставка цього тексту в термінал може бути небезпечною, оскільки виглядає "
|
||||
"так, ніби деякі команди можуть бути виконані."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:201
|
||||
msgid "Main Menu"
|
||||
msgstr "Головне меню"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:222
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Переглянути відкриті вкладки"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:249
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:312
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:744
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфігурацію перезавантажено"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:984
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Розробники Ghostty"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "Закрити"
|
||||
@ -270,10 +275,36 @@ msgid "The currently running process in this split will be terminated."
|
||||
msgstr ""
|
||||
"Поточний процес, що виконується в цій розділеній панелі, буде завершено."
|
||||
|
||||
#: src/apprt/gtk/Surface.zig:1243
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "Скопійовано в буфер обміну"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "Головне меню"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "Переглянути відкриті вкладки"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr ""
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr ""
|
||||
"⚠️ Ви використовуєте відладочну збірку Ghostty! Продуктивність буде погіршено."
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "Конфігурацію перезавантажено"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Розробники Ghostty"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty: Інспектор терміналу"
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: com.mitchellh.ghostty\n"
|
||||
"Report-Msgid-Bugs-To: m@mitchellh.com\n"
|
||||
"POT-Creation-Date: 2025-06-28 17:01+0200\n"
|
||||
"POT-Creation-Date: 2025-07-08 15:13-0500\n"
|
||||
"PO-Revision-Date: 2025-02-27 09:16+0100\n"
|
||||
"Last-Translator: Leah <hi@pluie.me>\n"
|
||||
"Language-Team: Chinese (simplified) <i18n-zh@googlegroups.com>\n"
|
||||
@ -125,7 +125,7 @@ msgstr "标签页"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-surface-context_menu.blp:62
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:30
|
||||
#: src/apprt/gtk/Window.zig:263
|
||||
#: src/apprt/gtk/Window.zig:265
|
||||
msgid "New Tab"
|
||||
msgstr "新建标签页"
|
||||
|
||||
@ -166,7 +166,7 @@ msgid "Terminal Inspector"
|
||||
msgstr "终端调试器"
|
||||
|
||||
#: src/apprt/gtk/ui/1.0/menu-window-titlebar_menu.blp:107
|
||||
#: src/apprt/gtk/Window.zig:1036
|
||||
#: src/apprt/gtk/Window.zig:1038
|
||||
msgid "About Ghostty"
|
||||
msgstr "关于 Ghostty"
|
||||
|
||||
@ -229,35 +229,6 @@ msgid ""
|
||||
"commands may be executed."
|
||||
msgstr "将以下内容粘贴至终端内将可能执行有害命令。"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "主菜单"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:238
|
||||
msgid "View Open Tabs"
|
||||
msgstr "浏览标签页"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:264
|
||||
msgid "New Split"
|
||||
msgstr "新建分屏"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:327
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Ghostty 正在以调试模式运行!性能将大打折扣。"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:773
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "已重新加载配置"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1017
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty 开发团队"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty 终端调试器"
|
||||
|
||||
#: src/apprt/gtk/CloseDialog.zig:47
|
||||
msgid "Close"
|
||||
msgstr "关闭"
|
||||
@ -297,3 +268,32 @@ msgstr "分屏内正在运行中的进程将被终止。"
|
||||
#: src/apprt/gtk/Surface.zig:1257
|
||||
msgid "Copied to clipboard"
|
||||
msgstr "已复制至剪贴板"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:216
|
||||
msgid "Main Menu"
|
||||
msgstr "主菜单"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:239
|
||||
msgid "View Open Tabs"
|
||||
msgstr "浏览标签页"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:266
|
||||
msgid "New Split"
|
||||
msgstr "新建分屏"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:329
|
||||
msgid ""
|
||||
"⚠️ You're running a debug build of Ghostty! Performance will be degraded."
|
||||
msgstr "⚠️ Ghostty 正在以调试模式运行!性能将大打折扣。"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:775
|
||||
msgid "Reloaded the configuration"
|
||||
msgstr "已重新加载配置"
|
||||
|
||||
#: src/apprt/gtk/Window.zig:1019
|
||||
msgid "Ghostty Developers"
|
||||
msgstr "Ghostty 开发团队"
|
||||
|
||||
#: src/apprt/gtk/inspector.zig:144
|
||||
msgid "Ghostty: Terminal Inspector"
|
||||
msgstr "Ghostty 终端调试器"
|
||||
|
@ -29,6 +29,7 @@ const apprt = @import("../../apprt.zig");
|
||||
const configpkg = @import("../../config.zig");
|
||||
const input = @import("../../input.zig");
|
||||
const internal_os = @import("../../os/main.zig");
|
||||
const systemd = @import("../../os/systemd.zig");
|
||||
const terminal = @import("../../terminal/main.zig");
|
||||
const Config = configpkg.Config;
|
||||
const CoreApp = @import("../../App.zig");
|
||||
@ -496,7 +497,7 @@ pub fn performAction(
|
||||
.resize_split => self.resizeSplit(target, value),
|
||||
.equalize_splits => self.equalizeSplits(target),
|
||||
.goto_split => return self.gotoSplit(target, value),
|
||||
.open_config => try configpkg.edit.open(self.core_app.alloc),
|
||||
.open_config => return self.openConfig(),
|
||||
.config_change => self.configChange(target, value.config),
|
||||
.reload_config => try self.reloadConfig(target, value),
|
||||
.inspector => self.controlInspector(target, value),
|
||||
@ -1035,6 +1036,12 @@ pub fn reloadConfig(
|
||||
target: apprt.action.Target,
|
||||
opts: apprt.action.ReloadConfig,
|
||||
) !void {
|
||||
// Tell systemd that reloading has started.
|
||||
systemd.notify.reloading();
|
||||
|
||||
// When we exit this function tell systemd that reloading has finished.
|
||||
defer systemd.notify.ready();
|
||||
|
||||
if (opts.soft) {
|
||||
switch (target) {
|
||||
.app => try self.core_app.updateConfig(self, &self.config),
|
||||
@ -1367,6 +1374,9 @@ pub fn run(self: *App) !void {
|
||||
log.warn("error handling configuration changes err={}", .{err});
|
||||
};
|
||||
|
||||
// Tell systemd that we are ready.
|
||||
systemd.notify.ready();
|
||||
|
||||
while (self.running) {
|
||||
_ = glib.MainContext.iteration(self.ctx, 1);
|
||||
|
||||
@ -1759,7 +1769,22 @@ fn initActions(self: *App) void {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn openUrl(
|
||||
fn openConfig(self: *App) !bool {
|
||||
// Get the config file path
|
||||
const alloc = self.core_app.alloc;
|
||||
const path = configpkg.edit.openPath(alloc) catch |err| {
|
||||
log.warn("error getting config file path: {}", .{err});
|
||||
return false;
|
||||
};
|
||||
defer alloc.free(path);
|
||||
|
||||
// Open it using openURL. "path" isn't actually a URL but
|
||||
// at the time of writing that works just fine for GTK.
|
||||
self.openUrl(.{ .kind = .text, .url = path });
|
||||
return true;
|
||||
}
|
||||
|
||||
fn openUrl(
|
||||
app: *App,
|
||||
value: apprt.action.OpenUrl,
|
||||
) void {
|
||||
|
@ -2333,6 +2333,7 @@ pub fn defaultTermioEnv(self: *Surface) !std.process.EnvMap {
|
||||
env.remove("DBUS_STARTER_BUS_TYPE");
|
||||
env.remove("INVOCATION_ID");
|
||||
env.remove("JOURNAL_STREAM");
|
||||
env.remove("NOTIFY_SOCKET");
|
||||
|
||||
// Unset environment varies set by snaps if we're running in a snap.
|
||||
// This allows Ghostty to further launch additional snaps.
|
||||
|
@ -103,7 +103,7 @@ pub inline fn runtimeUntil(
|
||||
test "atLeast" {
|
||||
const testing = std.testing;
|
||||
|
||||
const funs = &.{ atLeast, runtimeAtLeast, runtimeUntil };
|
||||
const funs = &.{ atLeast, runtimeAtLeast };
|
||||
inline for (funs) |fun| {
|
||||
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
|
||||
|
||||
@ -118,3 +118,23 @@ test "atLeast" {
|
||||
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION - 1, c.GTK_MICRO_VERSION + 1));
|
||||
}
|
||||
}
|
||||
|
||||
test "runtimeUntil" {
|
||||
const testing = std.testing;
|
||||
|
||||
// This is an array in case we add a comptime variant.
|
||||
const funs = &.{runtimeUntil};
|
||||
inline for (funs) |fun| {
|
||||
try testing.expect(!fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
|
||||
|
||||
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION + 1));
|
||||
try testing.expect(fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION + 1, c.GTK_MICRO_VERSION));
|
||||
try testing.expect(fun(c.GTK_MAJOR_VERSION + 1, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
|
||||
|
||||
try testing.expect(!fun(c.GTK_MAJOR_VERSION - 1, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION));
|
||||
try testing.expect(!fun(c.GTK_MAJOR_VERSION - 1, c.GTK_MINOR_VERSION + 1, c.GTK_MICRO_VERSION));
|
||||
try testing.expect(!fun(c.GTK_MAJOR_VERSION - 1, c.GTK_MINOR_VERSION, c.GTK_MICRO_VERSION + 1));
|
||||
|
||||
try testing.expect(!fun(c.GTK_MAJOR_VERSION, c.GTK_MINOR_VERSION - 1, c.GTK_MICRO_VERSION + 1));
|
||||
}
|
||||
}
|
||||
|
@ -115,7 +115,8 @@ pub fn init(b: *std.Build, cfg: *const Config) !GhosttyDist {
|
||||
// Capture stderr so it doesn't spew into the parent build.
|
||||
// On the flip side, if the test fails we won't know why so
|
||||
// that sucks but we should have already ran tests at this point.
|
||||
_ = step.captureStdErr();
|
||||
// NOTE(mitchellh): temporarily disabled to diagnose heisenbug
|
||||
//_ = step.captureStdErr();
|
||||
|
||||
break :step step;
|
||||
};
|
||||
|
@ -79,24 +79,38 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
|
||||
xgettext.has_side_effects = true;
|
||||
|
||||
inline for (gresource.blueprint_files) |blp| {
|
||||
// We avoid using addFileArg here since the full, absolute file path
|
||||
// would be added to the file as its location, which differs for
|
||||
// everyone's checkout of the repository.
|
||||
// This comes at a cost of losing per-file caching, of course.
|
||||
xgettext.addArg(std.fmt.comptimePrint(
|
||||
const path = std.fmt.comptimePrint(
|
||||
"src/apprt/gtk/ui/{[major]}.{[minor]}/{[name]s}.blp",
|
||||
blp,
|
||||
));
|
||||
);
|
||||
// The arguments to xgettext must be the relative path in the build root
|
||||
// or the resulting files will contain the absolute path. This will cause
|
||||
// a lot of churn because not everyone has the Ghostty code checked out in
|
||||
// exactly the same location.
|
||||
xgettext.addArg(path);
|
||||
// Mark the file as an input so that the Zig build system caching will work.
|
||||
xgettext.addFileInput(b.path(path));
|
||||
}
|
||||
|
||||
{
|
||||
var gtk_files = try b.build_root.handle.openDir(
|
||||
// Iterate over all of the files underneath `src/apprt/gtk`. We store
|
||||
// them in an array so that they can be sorted into a determininistic
|
||||
// order. That will minimize code churn as directory walking is not
|
||||
// guaranteed to happen in any particular order.
|
||||
|
||||
var gtk_files: std.ArrayListUnmanaged([]const u8) = .empty;
|
||||
defer {
|
||||
for (gtk_files.items) |item| b.allocator.free(item);
|
||||
gtk_files.deinit(b.allocator);
|
||||
}
|
||||
|
||||
var gtk_dir = try b.build_root.handle.openDir(
|
||||
"src/apprt/gtk",
|
||||
.{ .iterate = true },
|
||||
);
|
||||
defer gtk_files.close();
|
||||
defer gtk_dir.close();
|
||||
|
||||
var walk = try gtk_files.walk(b.allocator);
|
||||
var walk = try gtk_dir.walk(b.allocator);
|
||||
defer walk.deinit();
|
||||
while (try walk.next()) |src| {
|
||||
switch (src.kind) {
|
||||
@ -109,7 +123,29 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
|
||||
else => continue,
|
||||
}
|
||||
|
||||
xgettext.addArg((b.pathJoin(&.{ "src/apprt/gtk", src.path })));
|
||||
try gtk_files.append(b.allocator, try b.allocator.dupe(u8, src.path));
|
||||
}
|
||||
|
||||
std.mem.sort(
|
||||
[]const u8,
|
||||
gtk_files.items,
|
||||
{},
|
||||
struct {
|
||||
fn lt(_: void, lhs: []const u8, rhs: []const u8) bool {
|
||||
return std.mem.order(u8, lhs, rhs) == .lt;
|
||||
}
|
||||
}.lt,
|
||||
);
|
||||
|
||||
for (gtk_files.items) |item| {
|
||||
const path = b.pathJoin(&.{ "src/apprt/gtk", item });
|
||||
// The arguments to xgettext must be the relative path in the build root
|
||||
// or the resulting files will contain the absolute path. This will
|
||||
// cause a lot of churn because not everyone has the Ghostty code
|
||||
// checked out in exactly the same location.
|
||||
xgettext.addArg(path);
|
||||
// Mark the file as an input so that the Zig build system caching will work.
|
||||
xgettext.addFileInput(b.path(path));
|
||||
}
|
||||
}
|
||||
|
||||
@ -120,7 +156,7 @@ fn createUpdateStep(b: *std.Build) !*std.Build.Step {
|
||||
);
|
||||
|
||||
inline for (internal_os.i18n.locales) |locale| {
|
||||
const msgmerge = b.addSystemCommand(&.{ "msgmerge", "-q" });
|
||||
const msgmerge = b.addSystemCommand(&.{ "msgmerge", "--quiet", "--no-fuzzy-matching" });
|
||||
msgmerge.addFileArg(b.path("po/" ++ locale ++ ".po"));
|
||||
msgmerge.addFileArg(xgettext.captureStdOut());
|
||||
usf.addCopyFileToSource(msgmerge.captureStdOut(), "po/" ++ locale ++ ".po");
|
||||
|
@ -767,6 +767,9 @@ pub fn gtkDistResources(
|
||||
});
|
||||
const resources_c = generate_c.addOutputFileArg("ghostty_resources.c");
|
||||
generate_c.addFileArg(gresource_xml);
|
||||
for (gresource.dependencies) |file| {
|
||||
generate_c.addFileInput(b.path(file));
|
||||
}
|
||||
|
||||
const generate_h = b.addSystemCommand(&.{
|
||||
"glib-compile-resources",
|
||||
@ -777,6 +780,9 @@ pub fn gtkDistResources(
|
||||
});
|
||||
const resources_h = generate_h.addOutputFileArg("ghostty_resources.h");
|
||||
generate_h.addFileArg(gresource_xml);
|
||||
for (gresource.dependencies) |file| {
|
||||
generate_h.addFileInput(b.path(file));
|
||||
}
|
||||
|
||||
return .{
|
||||
.resources_c = .{
|
||||
|
@ -9,6 +9,7 @@ const list_keybinds = @import("list_keybinds.zig");
|
||||
const list_themes = @import("list_themes.zig");
|
||||
const list_colors = @import("list_colors.zig");
|
||||
const list_actions = @import("list_actions.zig");
|
||||
const ssh_cache = @import("ssh_cache.zig");
|
||||
const edit_config = @import("edit_config.zig");
|
||||
const show_config = @import("show_config.zig");
|
||||
const validate_config = @import("validate_config.zig");
|
||||
@ -41,6 +42,9 @@ pub const Action = enum {
|
||||
/// List keybind actions
|
||||
@"list-actions",
|
||||
|
||||
/// Manage SSH terminfo cache for automatic remote host setup
|
||||
@"ssh-cache",
|
||||
|
||||
/// Edit the config file in the configured terminal editor.
|
||||
@"edit-config",
|
||||
|
||||
@ -155,6 +159,7 @@ pub const Action = enum {
|
||||
.@"list-themes" => try list_themes.run(alloc),
|
||||
.@"list-colors" => try list_colors.run(alloc),
|
||||
.@"list-actions" => try list_actions.run(alloc),
|
||||
.@"ssh-cache" => try ssh_cache.run(alloc),
|
||||
.@"edit-config" => try edit_config.run(alloc),
|
||||
.@"show-config" => try show_config.run(alloc),
|
||||
.@"validate-config" => try validate_config.run(alloc),
|
||||
@ -192,6 +197,7 @@ pub const Action = enum {
|
||||
.@"list-themes" => list_themes.Options,
|
||||
.@"list-colors" => list_colors.Options,
|
||||
.@"list-actions" => list_actions.Options,
|
||||
.@"ssh-cache" => ssh_cache.Options,
|
||||
.@"edit-config" => edit_config.Options,
|
||||
.@"show-config" => show_config.Options,
|
||||
.@"validate-config" => validate_config.Options,
|
||||
|
549
src/cli/ssh-cache/DiskCache.zig
Normal file
549
src/cli/ssh-cache/DiskCache.zig
Normal file
@ -0,0 +1,549 @@
|
||||
/// An SSH terminfo entry cache that stores its cache data on
|
||||
/// disk. The cache only stores metadata (hostname, terminfo value,
|
||||
/// etc.) and does not store any sensitive data.
|
||||
const DiskCache = @This();
|
||||
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const xdg = @import("../../os/main.zig").xdg;
|
||||
const TempDir = @import("../../os/main.zig").TempDir;
|
||||
const Entry = @import("Entry.zig");
|
||||
|
||||
// 512KB - sufficient for approximately 10k entries
|
||||
const MAX_CACHE_SIZE = 512 * 1024;
|
||||
|
||||
/// Path to a file where the cache is stored.
|
||||
path: []const u8,
|
||||
|
||||
pub const DefaultPathError = Allocator.Error || error{
|
||||
/// The general error that is returned for any filesystem error
|
||||
/// that may have resulted in the XDG lookup failing.
|
||||
XdgLookupFailed,
|
||||
};
|
||||
|
||||
pub const Error = error{ CacheIsLocked, HostnameIsInvalid };
|
||||
|
||||
/// Returns the default path for the cache for a given program.
|
||||
///
|
||||
/// On all platforms, this is `${XDG_STATE_HOME}/ghostty/ssh_cache`.
|
||||
///
|
||||
/// The returned value is allocated and must be freed by the caller.
|
||||
pub fn defaultPath(
|
||||
alloc: Allocator,
|
||||
program: []const u8,
|
||||
) DefaultPathError![]const u8 {
|
||||
const state_dir: []const u8 = xdg.state(
|
||||
alloc,
|
||||
.{ .subdir = program },
|
||||
) catch |err| return switch (err) {
|
||||
error.OutOfMemory => error.OutOfMemory,
|
||||
else => error.XdgLookupFailed,
|
||||
};
|
||||
defer alloc.free(state_dir);
|
||||
return try std.fs.path.join(alloc, &.{ state_dir, "ssh_cache" });
|
||||
}
|
||||
|
||||
/// Clear all cache data stored in the disk cache.
|
||||
/// This removes the cache file from disk, effectively clearing all cached
|
||||
/// SSH terminfo entries.
|
||||
pub fn clear(self: DiskCache) !void {
|
||||
std.fs.cwd().deleteFile(self.path) catch |err| switch (err) {
|
||||
error.FileNotFound => {},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
|
||||
pub const AddResult = enum { added, updated };
|
||||
|
||||
/// Add or update a hostname entry in the cache.
|
||||
/// Returns AddResult.added for new entries or AddResult.updated for existing ones.
|
||||
/// The cache file is created if it doesn't exist with secure permissions (0600).
|
||||
pub fn add(
|
||||
self: DiskCache,
|
||||
alloc: Allocator,
|
||||
hostname: []const u8,
|
||||
) !AddResult {
|
||||
if (!isValidCacheKey(hostname)) return error.HostnameIsInvalid;
|
||||
|
||||
// Create cache directory if needed
|
||||
if (std.fs.path.dirname(self.path)) |dir| {
|
||||
std.fs.makeDirAbsolute(dir) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => {},
|
||||
else => return err,
|
||||
};
|
||||
}
|
||||
|
||||
// Open or create cache file with secure permissions
|
||||
const file = std.fs.createFileAbsolute(self.path, .{
|
||||
.read = true,
|
||||
.truncate = false,
|
||||
.mode = 0o600,
|
||||
}) catch |err| switch (err) {
|
||||
error.PathAlreadyExists => blk: {
|
||||
const existing_file = try std.fs.openFileAbsolute(
|
||||
self.path,
|
||||
.{ .mode = .read_write },
|
||||
);
|
||||
errdefer existing_file.close();
|
||||
try fixupPermissions(existing_file);
|
||||
break :blk existing_file;
|
||||
},
|
||||
else => return err,
|
||||
};
|
||||
defer file.close();
|
||||
|
||||
// Lock
|
||||
_ = file.tryLock(.exclusive) catch return error.CacheIsLocked;
|
||||
defer file.unlock();
|
||||
|
||||
var entries = try readEntries(alloc, file);
|
||||
defer deinitEntries(alloc, &entries);
|
||||
|
||||
// Add or update entry
|
||||
const gop = try entries.getOrPut(hostname);
|
||||
const result: AddResult = if (!gop.found_existing) add: {
|
||||
const hostname_copy = try alloc.dupe(u8, hostname);
|
||||
errdefer alloc.free(hostname_copy);
|
||||
const terminfo_copy = try alloc.dupe(u8, "xterm-ghostty");
|
||||
errdefer alloc.free(terminfo_copy);
|
||||
|
||||
gop.key_ptr.* = hostname_copy;
|
||||
gop.value_ptr.* = .{
|
||||
.hostname = gop.key_ptr.*,
|
||||
.timestamp = std.time.timestamp(),
|
||||
.terminfo_version = terminfo_copy,
|
||||
};
|
||||
break :add .added;
|
||||
} else update: {
|
||||
// Update timestamp for existing entry
|
||||
gop.value_ptr.timestamp = std.time.timestamp();
|
||||
break :update .updated;
|
||||
};
|
||||
|
||||
try self.writeCacheFile(alloc, entries, null);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Remove a hostname entry from the cache.
|
||||
/// No error is returned if the hostname doesn't exist or the cache file is missing.
|
||||
pub fn remove(
|
||||
self: DiskCache,
|
||||
alloc: Allocator,
|
||||
hostname: []const u8,
|
||||
) !void {
|
||||
if (!isValidCacheKey(hostname)) return error.HostnameIsInvalid;
|
||||
|
||||
// Open our file
|
||||
const file = std.fs.openFileAbsolute(
|
||||
self.path,
|
||||
.{ .mode = .read_write },
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => return,
|
||||
else => return err,
|
||||
};
|
||||
defer file.close();
|
||||
try fixupPermissions(file);
|
||||
|
||||
// Acquire exclusive lock
|
||||
_ = file.tryLock(.exclusive) catch return error.CacheIsLocked;
|
||||
defer file.unlock();
|
||||
|
||||
// Read existing entries
|
||||
var entries = try readEntries(alloc, file);
|
||||
defer deinitEntries(alloc, &entries);
|
||||
|
||||
// Remove the entry if it exists and ensure we free the memory
|
||||
if (entries.fetchRemove(hostname)) |kv| {
|
||||
assert(kv.key.ptr == kv.value.hostname.ptr);
|
||||
alloc.free(kv.value.hostname);
|
||||
alloc.free(kv.value.terminfo_version);
|
||||
}
|
||||
|
||||
try self.writeCacheFile(alloc, entries, null);
|
||||
}
|
||||
|
||||
/// Check if a hostname exists in the cache.
|
||||
/// Returns false if the cache file doesn't exist.
|
||||
pub fn contains(
|
||||
self: DiskCache,
|
||||
alloc: Allocator,
|
||||
hostname: []const u8,
|
||||
) !bool {
|
||||
if (!isValidCacheKey(hostname)) return error.HostnameIsInvalid;
|
||||
|
||||
// Open our file
|
||||
const file = std.fs.openFileAbsolute(
|
||||
self.path,
|
||||
.{ .mode = .read_write },
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => return false,
|
||||
else => return err,
|
||||
};
|
||||
defer file.close();
|
||||
try fixupPermissions(file);
|
||||
|
||||
// Read existing entries
|
||||
var entries = try readEntries(alloc, file);
|
||||
defer deinitEntries(alloc, &entries);
|
||||
|
||||
return entries.contains(hostname);
|
||||
}
|
||||
|
||||
fn fixupPermissions(file: std.fs.File) !void {
|
||||
// Ensure file has correct permissions (readable/writable by
|
||||
// owner only)
|
||||
const stat = try file.stat();
|
||||
if (stat.mode & 0o777 != 0o600) {
|
||||
try file.chmod(0o600);
|
||||
}
|
||||
}
|
||||
|
||||
fn writeCacheFile(
|
||||
self: DiskCache,
|
||||
alloc: Allocator,
|
||||
entries: std.StringHashMap(Entry),
|
||||
expire_days: ?u32,
|
||||
) !void {
|
||||
var td: TempDir = try .init();
|
||||
defer td.deinit();
|
||||
|
||||
const tmp_file = try td.dir.createFile("ssh-cache", .{ .mode = 0o600 });
|
||||
defer tmp_file.close();
|
||||
const tmp_path = try td.dir.realpathAlloc(alloc, "ssh-cache");
|
||||
defer alloc.free(tmp_path);
|
||||
|
||||
const writer = tmp_file.writer();
|
||||
var iter = entries.iterator();
|
||||
while (iter.next()) |kv| {
|
||||
// Only write non-expired entries
|
||||
if (kv.value_ptr.isExpired(expire_days)) continue;
|
||||
try kv.value_ptr.format(writer);
|
||||
}
|
||||
|
||||
// Atomic replace
|
||||
try std.fs.renameAbsolute(tmp_path, self.path);
|
||||
}
|
||||
|
||||
/// List all entries in the cache.
|
||||
/// The returned HashMap must be freed using `deinitEntries`.
|
||||
/// Returns an empty map if the cache file doesn't exist.
|
||||
pub fn list(
|
||||
self: DiskCache,
|
||||
alloc: Allocator,
|
||||
) !std.StringHashMap(Entry) {
|
||||
// Open our file
|
||||
const file = std.fs.openFileAbsolute(
|
||||
self.path,
|
||||
.{},
|
||||
) catch |err| switch (err) {
|
||||
error.FileNotFound => return .init(alloc),
|
||||
else => return err,
|
||||
};
|
||||
defer file.close();
|
||||
return readEntries(alloc, file);
|
||||
}
|
||||
|
||||
/// Free memory allocated by the `list` function.
|
||||
/// This must be called to properly deallocate all entry data.
|
||||
pub fn deinitEntries(
|
||||
alloc: Allocator,
|
||||
entries: *std.StringHashMap(Entry),
|
||||
) void {
|
||||
// All our entries we dupe the memory owned by the hostname and the
|
||||
// terminfo, and we always match the hostname key and value.
|
||||
var it = entries.iterator();
|
||||
while (it.next()) |entry| {
|
||||
assert(entry.key_ptr.*.ptr == entry.value_ptr.hostname.ptr);
|
||||
alloc.free(entry.value_ptr.hostname);
|
||||
alloc.free(entry.value_ptr.terminfo_version);
|
||||
}
|
||||
entries.deinit();
|
||||
}
|
||||
|
||||
fn readEntries(
|
||||
alloc: Allocator,
|
||||
file: std.fs.File,
|
||||
) !std.StringHashMap(Entry) {
|
||||
const content = try file.readToEndAlloc(alloc, MAX_CACHE_SIZE);
|
||||
defer alloc.free(content);
|
||||
|
||||
var entries = std.StringHashMap(Entry).init(alloc);
|
||||
var lines = std.mem.tokenizeScalar(u8, content, '\n');
|
||||
while (lines.next()) |line| {
|
||||
const trimmed = std.mem.trim(u8, line, " \t\r");
|
||||
const entry = Entry.parse(trimmed) orelse continue;
|
||||
|
||||
// Always allocate hostname first to avoid key pointer confusion
|
||||
const hostname = try alloc.dupe(u8, entry.hostname);
|
||||
errdefer alloc.free(hostname);
|
||||
|
||||
const gop = try entries.getOrPut(hostname);
|
||||
if (!gop.found_existing) {
|
||||
const terminfo_copy = try alloc.dupe(u8, entry.terminfo_version);
|
||||
gop.value_ptr.* = .{
|
||||
.hostname = hostname,
|
||||
.timestamp = entry.timestamp,
|
||||
.terminfo_version = terminfo_copy,
|
||||
};
|
||||
} else {
|
||||
// Don't need the copy since entry already exists
|
||||
alloc.free(hostname);
|
||||
|
||||
// Handle duplicate entries - keep newer timestamp
|
||||
if (entry.timestamp > gop.value_ptr.timestamp) {
|
||||
gop.value_ptr.timestamp = entry.timestamp;
|
||||
if (!std.mem.eql(
|
||||
u8,
|
||||
gop.value_ptr.terminfo_version,
|
||||
entry.terminfo_version,
|
||||
)) {
|
||||
alloc.free(gop.value_ptr.terminfo_version);
|
||||
const terminfo_copy = try alloc.dupe(u8, entry.terminfo_version);
|
||||
gop.value_ptr.terminfo_version = terminfo_copy;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
|
||||
// Supports both standalone hostnames and user@hostname format
|
||||
fn isValidCacheKey(key: []const u8) bool {
|
||||
// 253 + 1 + 64 for user@hostname
|
||||
if (key.len == 0 or key.len > 320) return false;
|
||||
|
||||
// Check for user@hostname format
|
||||
if (std.mem.indexOf(u8, key, "@")) |at_pos| {
|
||||
const user = key[0..at_pos];
|
||||
const hostname = key[at_pos + 1 ..];
|
||||
return isValidUser(user) and isValidHostname(hostname);
|
||||
}
|
||||
|
||||
return isValidHostname(key);
|
||||
}
|
||||
|
||||
// Basic hostname validation - accepts domains and IPs
|
||||
// (including IPv6 in brackets)
|
||||
fn isValidHostname(host: []const u8) bool {
|
||||
if (host.len == 0 or host.len > 253) return false;
|
||||
|
||||
// Handle IPv6 addresses in brackets
|
||||
if (host.len >= 4 and host[0] == '[' and host[host.len - 1] == ']') {
|
||||
const ipv6_part = host[1 .. host.len - 1];
|
||||
if (ipv6_part.len == 0) return false;
|
||||
var has_colon = false;
|
||||
for (ipv6_part) |c| {
|
||||
switch (c) {
|
||||
'a'...'f', 'A'...'F', '0'...'9' => {},
|
||||
':' => has_colon = true,
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
return has_colon;
|
||||
}
|
||||
|
||||
// Standard hostname/domain validation
|
||||
for (host) |c| {
|
||||
switch (c) {
|
||||
'a'...'z', 'A'...'Z', '0'...'9', '.', '-' => {},
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
|
||||
// No leading/trailing dots or hyphens, no consecutive dots
|
||||
if (host[0] == '.' or host[0] == '-' or
|
||||
host[host.len - 1] == '.' or host[host.len - 1] == '-')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return std.mem.indexOf(u8, host, "..") == null;
|
||||
}
|
||||
|
||||
fn isValidUser(user: []const u8) bool {
|
||||
if (user.len == 0 or user.len > 64) return false;
|
||||
for (user) |c| {
|
||||
switch (c) {
|
||||
'a'...'z', 'A'...'Z', '0'...'9', '_', '-', '.' => {},
|
||||
else => return false,
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
test "disk cache default path" {
|
||||
const testing = std.testing;
|
||||
const alloc = std.testing.allocator;
|
||||
|
||||
const path = try DiskCache.defaultPath(alloc, "ghostty");
|
||||
defer alloc.free(path);
|
||||
try testing.expect(path.len > 0);
|
||||
}
|
||||
|
||||
test "disk cache clear" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
// Create our path
|
||||
var td: TempDir = try .init();
|
||||
defer td.deinit();
|
||||
{
|
||||
var file = try td.dir.createFile("cache", .{});
|
||||
defer file.close();
|
||||
try file.writer().writeAll("HELLO!");
|
||||
}
|
||||
const path = try td.dir.realpathAlloc(alloc, "cache");
|
||||
defer alloc.free(path);
|
||||
|
||||
// Setup our cache
|
||||
const cache: DiskCache = .{ .path = path };
|
||||
try cache.clear();
|
||||
|
||||
// Verify the file is gone
|
||||
try testing.expectError(
|
||||
error.FileNotFound,
|
||||
td.dir.openFile("cache", .{}),
|
||||
);
|
||||
}
|
||||
|
||||
test "disk cache operations" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
|
||||
// Create our path
|
||||
var td: TempDir = try .init();
|
||||
defer td.deinit();
|
||||
{
|
||||
var file = try td.dir.createFile("cache", .{});
|
||||
defer file.close();
|
||||
try file.writer().writeAll("HELLO!");
|
||||
}
|
||||
const path = try td.dir.realpathAlloc(alloc, "cache");
|
||||
defer alloc.free(path);
|
||||
|
||||
// Setup our cache
|
||||
const cache: DiskCache = .{ .path = path };
|
||||
try testing.expectEqual(
|
||||
AddResult.added,
|
||||
try cache.add(alloc, "example.com"),
|
||||
);
|
||||
try testing.expectEqual(
|
||||
AddResult.updated,
|
||||
try cache.add(alloc, "example.com"),
|
||||
);
|
||||
try testing.expect(
|
||||
try cache.contains(alloc, "example.com"),
|
||||
);
|
||||
|
||||
// List
|
||||
var entries = try cache.list(alloc);
|
||||
deinitEntries(alloc, &entries);
|
||||
|
||||
// Remove
|
||||
try cache.remove(alloc, "example.com");
|
||||
try testing.expect(
|
||||
!(try cache.contains(alloc, "example.com")),
|
||||
);
|
||||
try testing.expectEqual(
|
||||
AddResult.added,
|
||||
try cache.add(alloc, "example.com"),
|
||||
);
|
||||
}
|
||||
|
||||
// Tests
|
||||
test "hostname validation - valid cases" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(isValidHostname("example.com"));
|
||||
try testing.expect(isValidHostname("sub.example.com"));
|
||||
try testing.expect(isValidHostname("host-name.domain.org"));
|
||||
try testing.expect(isValidHostname("192.168.1.1"));
|
||||
try testing.expect(isValidHostname("a"));
|
||||
try testing.expect(isValidHostname("1"));
|
||||
}
|
||||
|
||||
test "hostname validation - IPv6 addresses" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(isValidHostname("[::1]"));
|
||||
try testing.expect(isValidHostname("[2001:db8::1]"));
|
||||
try testing.expect(!isValidHostname("[fe80::1%eth0]")); // Interface notation not supported
|
||||
try testing.expect(!isValidHostname("[]")); // Empty IPv6
|
||||
try testing.expect(!isValidHostname("[invalid]")); // No colons
|
||||
}
|
||||
|
||||
test "hostname validation - invalid cases" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(!isValidHostname(""));
|
||||
try testing.expect(!isValidHostname("host\nname"));
|
||||
try testing.expect(!isValidHostname(".example.com"));
|
||||
try testing.expect(!isValidHostname("example.com."));
|
||||
try testing.expect(!isValidHostname("host..domain"));
|
||||
try testing.expect(!isValidHostname("-hostname"));
|
||||
try testing.expect(!isValidHostname("hostname-"));
|
||||
try testing.expect(!isValidHostname("host name"));
|
||||
try testing.expect(!isValidHostname("host_name"));
|
||||
try testing.expect(!isValidHostname("host@domain"));
|
||||
try testing.expect(!isValidHostname("host:port"));
|
||||
|
||||
// Too long
|
||||
const long_host = "a" ** 254;
|
||||
try testing.expect(!isValidHostname(long_host));
|
||||
}
|
||||
|
||||
test "user validation - valid cases" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(isValidUser("user"));
|
||||
try testing.expect(isValidUser("deploy"));
|
||||
try testing.expect(isValidUser("test-user"));
|
||||
try testing.expect(isValidUser("user_name"));
|
||||
try testing.expect(isValidUser("user.name"));
|
||||
try testing.expect(isValidUser("user123"));
|
||||
try testing.expect(isValidUser("a"));
|
||||
}
|
||||
|
||||
test "user validation - complex realistic cases" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(isValidUser("git"));
|
||||
try testing.expect(isValidUser("ubuntu"));
|
||||
try testing.expect(isValidUser("root"));
|
||||
try testing.expect(isValidUser("service.account"));
|
||||
try testing.expect(isValidUser("user-with-dashes"));
|
||||
}
|
||||
|
||||
test "user validation - invalid cases" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(!isValidUser(""));
|
||||
try testing.expect(!isValidUser("user name"));
|
||||
try testing.expect(!isValidUser("user@domain"));
|
||||
try testing.expect(!isValidUser("user:group"));
|
||||
try testing.expect(!isValidUser("user\nname"));
|
||||
|
||||
// Too long
|
||||
const long_user = "a" ** 65;
|
||||
try testing.expect(!isValidUser(long_user));
|
||||
}
|
||||
|
||||
test "cache key validation - hostname format" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(isValidCacheKey("example.com"));
|
||||
try testing.expect(isValidCacheKey("sub.example.com"));
|
||||
try testing.expect(isValidCacheKey("192.168.1.1"));
|
||||
try testing.expect(isValidCacheKey("[::1]"));
|
||||
try testing.expect(!isValidCacheKey(""));
|
||||
try testing.expect(!isValidCacheKey(".invalid.com"));
|
||||
}
|
||||
|
||||
test "cache key validation - user@hostname format" {
|
||||
const testing = std.testing;
|
||||
try testing.expect(isValidCacheKey("user@example.com"));
|
||||
try testing.expect(isValidCacheKey("deploy@prod.server.com"));
|
||||
try testing.expect(isValidCacheKey("test-user@192.168.1.1"));
|
||||
try testing.expect(isValidCacheKey("user_name@host.domain.org"));
|
||||
try testing.expect(isValidCacheKey("git@github.com"));
|
||||
try testing.expect(isValidCacheKey("ubuntu@[::1]"));
|
||||
try testing.expect(!isValidCacheKey("@example.com"));
|
||||
try testing.expect(!isValidCacheKey("user@"));
|
||||
try testing.expect(!isValidCacheKey("user@@host"));
|
||||
try testing.expect(!isValidCacheKey("user@.invalid.com"));
|
||||
}
|
154
src/cli/ssh-cache/Entry.zig
Normal file
154
src/cli/ssh-cache/Entry.zig
Normal file
@ -0,0 +1,154 @@
|
||||
/// A single entry within our SSH entry cache. Our SSH entry cache
|
||||
/// stores which hosts we've sent our terminfo to so that we don't have
|
||||
/// to send it again. It doesn't store any sensitive information.
|
||||
const Entry = @This();
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
hostname: []const u8,
|
||||
timestamp: i64,
|
||||
terminfo_version: []const u8,
|
||||
|
||||
pub fn parse(line: []const u8) ?Entry {
|
||||
const trimmed = std.mem.trim(u8, line, " \t\r\n");
|
||||
if (trimmed.len == 0) return null;
|
||||
|
||||
// Parse format: hostname|timestamp|terminfo_version
|
||||
var iter = std.mem.tokenizeScalar(u8, trimmed, '|');
|
||||
const hostname = iter.next() orelse return null;
|
||||
const timestamp_str = iter.next() orelse return null;
|
||||
const terminfo_version = iter.next() orelse "xterm-ghostty";
|
||||
const timestamp = std.fmt.parseInt(i64, timestamp_str, 10) catch |err| {
|
||||
std.log.warn(
|
||||
"Invalid timestamp in cache entry: {s} err={}",
|
||||
.{ timestamp_str, err },
|
||||
);
|
||||
return null;
|
||||
};
|
||||
|
||||
return .{
|
||||
.hostname = hostname,
|
||||
.timestamp = timestamp,
|
||||
.terminfo_version = terminfo_version,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn format(self: Entry, writer: anytype) !void {
|
||||
try writer.print(
|
||||
"{s}|{d}|{s}\n",
|
||||
.{ self.hostname, self.timestamp, self.terminfo_version },
|
||||
);
|
||||
}
|
||||
|
||||
pub fn isExpired(self: Entry, expire_days_: ?u32) bool {
|
||||
const expire_days = expire_days_ orelse return false;
|
||||
const now = std.time.timestamp();
|
||||
const age_days = @divTrunc(now -| self.timestamp, std.time.s_per_day);
|
||||
return age_days > expire_days;
|
||||
}
|
||||
|
||||
test "cache entry expiration" {
|
||||
const testing = std.testing;
|
||||
const now = std.time.timestamp();
|
||||
|
||||
const fresh_entry: Entry = .{
|
||||
.hostname = "test.com",
|
||||
.timestamp = now - std.time.s_per_day, // 1 day old
|
||||
.terminfo_version = "xterm-ghostty",
|
||||
};
|
||||
try testing.expect(!fresh_entry.isExpired(90));
|
||||
|
||||
const old_entry: Entry = .{
|
||||
.hostname = "old.com",
|
||||
.timestamp = now - (std.time.s_per_day * 100), // 100 days old
|
||||
.terminfo_version = "xterm-ghostty",
|
||||
};
|
||||
try testing.expect(old_entry.isExpired(90));
|
||||
|
||||
// Test never-expire case
|
||||
try testing.expect(!old_entry.isExpired(null));
|
||||
}
|
||||
|
||||
test "cache entry expiration exact boundary" {
|
||||
const testing = std.testing;
|
||||
const now = std.time.timestamp();
|
||||
|
||||
// Exactly at expiration boundary
|
||||
const boundary_entry: Entry = .{
|
||||
.hostname = "example.com",
|
||||
.timestamp = now - (std.time.s_per_day * 30),
|
||||
.terminfo_version = "xterm-ghostty",
|
||||
};
|
||||
try testing.expect(!boundary_entry.isExpired(30));
|
||||
try testing.expect(boundary_entry.isExpired(29));
|
||||
}
|
||||
|
||||
test "cache entry expiration large timestamp" {
|
||||
const testing = std.testing;
|
||||
const now = std.time.timestamp();
|
||||
|
||||
const boundary_entry: Entry = .{
|
||||
.hostname = "example.com",
|
||||
.timestamp = now + (std.time.s_per_day * 30),
|
||||
.terminfo_version = "xterm-ghostty",
|
||||
};
|
||||
try testing.expect(!boundary_entry.isExpired(30));
|
||||
}
|
||||
|
||||
test "cache entry parsing valid formats" {
|
||||
const testing = std.testing;
|
||||
|
||||
const entry = Entry.parse("example.com|1640995200|xterm-ghostty").?;
|
||||
try testing.expectEqualStrings("example.com", entry.hostname);
|
||||
try testing.expectEqual(@as(i64, 1640995200), entry.timestamp);
|
||||
try testing.expectEqualStrings("xterm-ghostty", entry.terminfo_version);
|
||||
|
||||
// Test default terminfo version
|
||||
const entry_no_version = Entry.parse("test.com|1640995200").?;
|
||||
try testing.expectEqualStrings(
|
||||
"xterm-ghostty",
|
||||
entry_no_version.terminfo_version,
|
||||
);
|
||||
|
||||
// Test complex hostnames
|
||||
const complex_entry = Entry.parse("user@server.example.com|1640995200|xterm-ghostty").?;
|
||||
try testing.expectEqualStrings(
|
||||
"user@server.example.com",
|
||||
complex_entry.hostname,
|
||||
);
|
||||
}
|
||||
|
||||
test "cache entry parsing invalid formats" {
|
||||
const testing = std.testing;
|
||||
|
||||
try testing.expect(Entry.parse("") == null);
|
||||
|
||||
// Invalid format (no pipe)
|
||||
try testing.expect(Entry.parse("v1") == null);
|
||||
|
||||
// Missing timestamp
|
||||
try testing.expect(Entry.parse("example.com") == null);
|
||||
|
||||
// Invalid timestamp
|
||||
try testing.expect(Entry.parse("example.com|invalid") == null);
|
||||
|
||||
// Empty terminfo should default
|
||||
try testing.expect(Entry.parse("example.com|1640995200|") != null);
|
||||
}
|
||||
|
||||
test "cache entry parsing malformed data resilience" {
|
||||
const testing = std.testing;
|
||||
|
||||
// Extra pipes should not break parsing
|
||||
try testing.expect(Entry.parse("host|123|term|extra") != null);
|
||||
|
||||
// Whitespace handling
|
||||
try testing.expect(Entry.parse(" host|123|term ") != null);
|
||||
try testing.expect(Entry.parse("\n") == null);
|
||||
try testing.expect(Entry.parse(" \t \n") == null);
|
||||
|
||||
// Extremely large timestamp
|
||||
try testing.expect(
|
||||
Entry.parse("host|999999999999999999999999999999999999999999999999|xterm-ghostty") == null,
|
||||
);
|
||||
}
|
208
src/cli/ssh_cache.zig
Normal file
208
src/cli/ssh_cache.zig
Normal file
@ -0,0 +1,208 @@
|
||||
const std = @import("std");
|
||||
const fs = std.fs;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const xdg = @import("../os/xdg.zig");
|
||||
const args = @import("args.zig");
|
||||
const Action = @import("action.zig").Action;
|
||||
pub const Entry = @import("ssh-cache/Entry.zig");
|
||||
pub const DiskCache = @import("ssh-cache/DiskCache.zig");
|
||||
|
||||
pub const Options = struct {
|
||||
clear: bool = false,
|
||||
add: ?[]const u8 = null,
|
||||
remove: ?[]const u8 = null,
|
||||
host: ?[]const u8 = null,
|
||||
@"expire-days": ?u32 = null,
|
||||
|
||||
pub fn deinit(self: *Options) void {
|
||||
_ = self;
|
||||
}
|
||||
|
||||
pub fn help(self: Options) !void {
|
||||
_ = self;
|
||||
return Action.help_error;
|
||||
}
|
||||
};
|
||||
|
||||
/// Manage the SSH terminfo cache for automatic remote host setup.
|
||||
///
|
||||
/// When SSH integration is enabled with `shell-integration-features = ssh-terminfo`,
|
||||
/// Ghostty automatically installs its terminfo on remote hosts. This command
|
||||
/// manages the cache of successful installations to avoid redundant uploads.
|
||||
///
|
||||
/// The cache stores hostnames (or user@hostname combinations) along with timestamps.
|
||||
/// Entries older than the expiration period are automatically removed during cache
|
||||
/// operations. By default, entries never expire.
|
||||
///
|
||||
/// Only one of `--clear`, `--add`, `--remove`, or `--host` can be specified.
|
||||
/// If multiple are specified, one of the actions will be executed but
|
||||
/// it isn't guaranteed which one. This is entirely unsafe so you should split
|
||||
/// multiple actions into separate commands.
|
||||
///
|
||||
/// Examples:
|
||||
/// ghostty +ssh-cache # List all cached hosts
|
||||
/// ghostty +ssh-cache --host=example.com # Check if host is cached
|
||||
/// ghostty +ssh-cache --add=example.com # Manually add host to cache
|
||||
/// ghostty +ssh-cache --add=user@example.com # Add user@host combination
|
||||
/// ghostty +ssh-cache --remove=example.com # Remove host from cache
|
||||
/// ghostty +ssh-cache --clear # Clear entire cache
|
||||
/// ghostty +ssh-cache --expire-days=30 # Set custom expiration period
|
||||
pub fn run(alloc_gpa: Allocator) !u8 {
|
||||
var arena = std.heap.ArenaAllocator.init(alloc_gpa);
|
||||
defer arena.deinit();
|
||||
const alloc = arena.allocator();
|
||||
|
||||
var opts: Options = .{};
|
||||
defer opts.deinit();
|
||||
|
||||
{
|
||||
var iter = try args.argsIterator(alloc_gpa);
|
||||
defer iter.deinit();
|
||||
try args.parse(Options, alloc_gpa, &opts, &iter);
|
||||
}
|
||||
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
const stderr = std.io.getStdErr().writer();
|
||||
|
||||
// Setup our disk cache to the standard location
|
||||
const cache_path = try DiskCache.defaultPath(alloc, "ghostty");
|
||||
const cache: DiskCache = .{ .path = cache_path };
|
||||
|
||||
if (opts.clear) {
|
||||
try cache.clear();
|
||||
try stdout.print("Cache cleared.\n", .{});
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.add) |host| {
|
||||
const result = cache.add(alloc, host) catch |err| switch (err) {
|
||||
DiskCache.Error.HostnameIsInvalid => {
|
||||
try stderr.print("Error: Invalid hostname format '{s}'\n", .{host});
|
||||
try stderr.print("Expected format: hostname or user@hostname\n", .{});
|
||||
return 1;
|
||||
},
|
||||
DiskCache.Error.CacheIsLocked => {
|
||||
try stderr.print("Error: Cache is busy, try again\n", .{});
|
||||
return 1;
|
||||
},
|
||||
else => {
|
||||
try stderr.print(
|
||||
"Error: Unable to add '{s}' to cache. Error: {}\n",
|
||||
.{ host, err },
|
||||
);
|
||||
return 1;
|
||||
},
|
||||
};
|
||||
|
||||
switch (result) {
|
||||
.added => try stdout.print("Added '{s}' to cache.\n", .{host}),
|
||||
.updated => try stdout.print("Updated '{s}' cache entry.\n", .{host}),
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.remove) |host| {
|
||||
cache.remove(alloc, host) catch |err| switch (err) {
|
||||
DiskCache.Error.HostnameIsInvalid => {
|
||||
try stderr.print("Error: Invalid hostname format '{s}'\n", .{host});
|
||||
try stderr.print("Expected format: hostname or user@hostname\n", .{});
|
||||
return 1;
|
||||
},
|
||||
DiskCache.Error.CacheIsLocked => {
|
||||
try stderr.print("Error: Cache is busy, try again\n", .{});
|
||||
return 1;
|
||||
},
|
||||
else => {
|
||||
try stderr.print(
|
||||
"Error: Unable to remove '{s}' from cache. Error: {}\n",
|
||||
.{ host, err },
|
||||
);
|
||||
return 1;
|
||||
},
|
||||
};
|
||||
try stdout.print("Removed '{s}' from cache.\n", .{host});
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.host) |host| {
|
||||
const cached = cache.contains(alloc, host) catch |err| switch (err) {
|
||||
error.HostnameIsInvalid => {
|
||||
try stderr.print("Error: Invalid hostname format '{s}'\n", .{host});
|
||||
try stderr.print("Expected format: hostname or user@hostname\n", .{});
|
||||
return 1;
|
||||
},
|
||||
else => {
|
||||
try stderr.print(
|
||||
"Error: Unable to check host '{s}' in cache. Error: {}\n",
|
||||
.{ host, err },
|
||||
);
|
||||
return 1;
|
||||
},
|
||||
};
|
||||
|
||||
if (cached) {
|
||||
try stdout.print(
|
||||
"'{s}' has Ghostty terminfo installed.\n",
|
||||
.{host},
|
||||
);
|
||||
return 0;
|
||||
} else {
|
||||
try stdout.print(
|
||||
"'{s}' does not have Ghostty terminfo installed.\n",
|
||||
.{host},
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Default action: list all hosts
|
||||
var entries = try cache.list(alloc);
|
||||
defer DiskCache.deinitEntries(alloc, &entries);
|
||||
try listEntries(alloc, &entries, stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn listEntries(
|
||||
alloc: Allocator,
|
||||
entries: *const std.StringHashMap(Entry),
|
||||
writer: anytype,
|
||||
) !void {
|
||||
if (entries.count() == 0) {
|
||||
try writer.print("No hosts in cache.\n", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
// Sort entries by hostname for consistent output
|
||||
var items = std.ArrayList(Entry).init(alloc);
|
||||
defer items.deinit();
|
||||
|
||||
var iter = entries.iterator();
|
||||
while (iter.next()) |kv| {
|
||||
try items.append(kv.value_ptr.*);
|
||||
}
|
||||
|
||||
std.mem.sort(Entry, items.items, {}, struct {
|
||||
fn lessThan(_: void, a: Entry, b: Entry) bool {
|
||||
return std.mem.lessThan(u8, a.hostname, b.hostname);
|
||||
}
|
||||
}.lessThan);
|
||||
|
||||
try writer.print("Cached hosts ({d}):\n", .{items.items.len});
|
||||
const now = std.time.timestamp();
|
||||
|
||||
for (items.items) |entry| {
|
||||
const age_days = @divTrunc(now - entry.timestamp, std.time.s_per_day);
|
||||
if (age_days == 0) {
|
||||
try writer.print(" {s} (today)\n", .{entry.hostname});
|
||||
} else if (age_days == 1) {
|
||||
try writer.print(" {s} (yesterday)\n", .{entry.hostname});
|
||||
} else {
|
||||
try writer.print(" {s} ({d} days ago)\n", .{ entry.hostname, age_days });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
test {
|
||||
_ = DiskCache;
|
||||
_ = Entry;
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
const std = @import("std");
|
||||
const assert = std.debug.assert;
|
||||
const cli = @import("../cli.zig");
|
||||
const inputpkg = @import("../input.zig");
|
||||
const global = &@import("../global.zig").state;
|
||||
const state = &@import("../global.zig").state;
|
||||
const c = @import("../main_c.zig");
|
||||
|
||||
const Config = @import("Config.zig");
|
||||
const c_get = @import("c_get.zig");
|
||||
@ -12,14 +14,14 @@ const log = std.log.scoped(.config);
|
||||
|
||||
/// Create a new configuration filled with the initial default values.
|
||||
export fn ghostty_config_new() ?*Config {
|
||||
const result = global.alloc.create(Config) catch |err| {
|
||||
const result = state.alloc.create(Config) catch |err| {
|
||||
log.err("error allocating config err={}", .{err});
|
||||
return null;
|
||||
};
|
||||
|
||||
result.* = Config.default(global.alloc) catch |err| {
|
||||
result.* = Config.default(state.alloc) catch |err| {
|
||||
log.err("error creating config err={}", .{err});
|
||||
global.alloc.destroy(result);
|
||||
state.alloc.destroy(result);
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -29,20 +31,20 @@ export fn ghostty_config_new() ?*Config {
|
||||
export fn ghostty_config_free(ptr: ?*Config) void {
|
||||
if (ptr) |v| {
|
||||
v.deinit();
|
||||
global.alloc.destroy(v);
|
||||
state.alloc.destroy(v);
|
||||
}
|
||||
}
|
||||
|
||||
/// Deep clone the configuration.
|
||||
export fn ghostty_config_clone(self: *Config) ?*Config {
|
||||
const result = global.alloc.create(Config) catch |err| {
|
||||
const result = state.alloc.create(Config) catch |err| {
|
||||
log.err("error allocating config err={}", .{err});
|
||||
return null;
|
||||
};
|
||||
|
||||
result.* = self.clone(global.alloc) catch |err| {
|
||||
result.* = self.clone(state.alloc) catch |err| {
|
||||
log.err("error cloning config err={}", .{err});
|
||||
global.alloc.destroy(result);
|
||||
state.alloc.destroy(result);
|
||||
return null;
|
||||
};
|
||||
|
||||
@ -51,7 +53,7 @@ export fn ghostty_config_clone(self: *Config) ?*Config {
|
||||
|
||||
/// Load the configuration from the CLI args.
|
||||
export fn ghostty_config_load_cli_args(self: *Config) void {
|
||||
self.loadCliArgs(global.alloc) catch |err| {
|
||||
self.loadCliArgs(state.alloc) catch |err| {
|
||||
log.err("error loading config err={}", .{err});
|
||||
};
|
||||
}
|
||||
@ -60,7 +62,7 @@ export fn ghostty_config_load_cli_args(self: *Config) void {
|
||||
/// is usually done first. The default file locations are locations
|
||||
/// such as the home directory.
|
||||
export fn ghostty_config_load_default_files(self: *Config) void {
|
||||
self.loadDefaultFiles(global.alloc) catch |err| {
|
||||
self.loadDefaultFiles(state.alloc) catch |err| {
|
||||
log.err("error loading config err={}", .{err});
|
||||
};
|
||||
}
|
||||
@ -69,7 +71,7 @@ export fn ghostty_config_load_default_files(self: *Config) void {
|
||||
/// file locations in the previously loaded configuration. This will
|
||||
/// recursively continue to load up to a built-in limit.
|
||||
export fn ghostty_config_load_recursive_files(self: *Config) void {
|
||||
self.loadRecursiveFiles(global.alloc) catch |err| {
|
||||
self.loadRecursiveFiles(state.alloc) catch |err| {
|
||||
log.err("error loading config err={}", .{err});
|
||||
};
|
||||
}
|
||||
@ -122,10 +124,13 @@ export fn ghostty_config_get_diagnostic(self: *Config, idx: u32) Diagnostic {
|
||||
return .{ .message = message.ptr };
|
||||
}
|
||||
|
||||
export fn ghostty_config_open() void {
|
||||
edit.open(global.alloc) catch |err| {
|
||||
export fn ghostty_config_open_path() c.String {
|
||||
const path = edit.openPath(state.alloc) catch |err| {
|
||||
log.err("error opening config in editor err={}", .{err});
|
||||
return .empty;
|
||||
};
|
||||
|
||||
return .fromSlice(path);
|
||||
}
|
||||
|
||||
/// Sync with ghostty_diagnostic_s
|
||||
|
@ -305,6 +305,7 @@ pub const compatibility = std.StaticStringMap(
|
||||
///
|
||||
/// * `cursor` - Break runs under the cursor.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"font-shaping-break": FontShapingBreak = .{},
|
||||
|
||||
/// What color space to use when performing alpha blending.
|
||||
@ -329,6 +330,8 @@ pub const compatibility = std.StaticStringMap(
|
||||
/// * `linear-corrected` - Same as `linear`, but with a correction step applied
|
||||
/// for text that makes it look nearly or completely identical to `native`,
|
||||
/// but without any of the darkening artifacts.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"alpha-blending": AlphaBlending =
|
||||
if (builtin.os.tag == .macos)
|
||||
.native
|
||||
@ -396,6 +399,20 @@ pub const compatibility = std.StaticStringMap(
|
||||
/// Thickness in pixels or percentage adjustment of box drawing characters.
|
||||
/// See the notes about adjustments in `adjust-cell-width`.
|
||||
@"adjust-box-thickness": ?MetricModifier = null,
|
||||
/// Height in pixels or percentage adjustment of maximum height for nerd font icons.
|
||||
///
|
||||
/// Increasing this value will allow nerd font icons to be larger, but won't
|
||||
/// necessarily force them to be. Decreasing this value will make nerd font
|
||||
/// icons smaller.
|
||||
///
|
||||
/// The default value for the icon height is 1.2 times the height of capital
|
||||
/// letters in your primary font, so something like -16.6% would make icons
|
||||
/// roughly the same height as capital letters.
|
||||
///
|
||||
/// See the notes about adjustments in `adjust-cell-width`.
|
||||
///
|
||||
/// Available in: 1.2.0
|
||||
@"adjust-icon-height": ?MetricModifier = null,
|
||||
|
||||
/// The method to use for calculating the cell width of a grapheme cluster.
|
||||
/// The default value is `unicode` which uses the Unicode standard to determine
|
||||
@ -503,7 +520,6 @@ pub const compatibility = std.StaticStringMap(
|
||||
/// be fixed in a future update:
|
||||
///
|
||||
/// - macOS: titlebar tabs style is not updated when switching themes.
|
||||
///
|
||||
theme: ?Theme = null,
|
||||
|
||||
/// Background color for the window.
|
||||
@ -527,6 +543,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||
/// For sufficiently large images, this could lead to a large increase in
|
||||
/// memory usage (specifically VRAM usage). A future Ghostty improvement
|
||||
/// will resolve this by sharing image textures across terminals.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"background-image": ?Path = null,
|
||||
|
||||
/// Background image opacity.
|
||||
@ -546,6 +564,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||
/// configured `background-opacity` is `0.5` and `background-image-opacity`
|
||||
/// is set to `1.5`, then the final opacity of the background image will be
|
||||
/// `0.5 * 1.5 = 0.75`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"background-image-opacity": f32 = 1.0,
|
||||
|
||||
/// Background image position.
|
||||
@ -562,6 +582,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||
/// * `bottom-right`
|
||||
///
|
||||
/// The default value is `center`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"background-image-position": BackgroundImagePosition = .center,
|
||||
|
||||
/// Background image fit.
|
||||
@ -590,6 +612,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||
/// Don't scale the background image.
|
||||
///
|
||||
/// The default value is `contain`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"background-image-fit": BackgroundImageFit = .contain,
|
||||
|
||||
/// Whether to repeat the background image or not.
|
||||
@ -599,6 +623,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||
/// fill the terminal area.
|
||||
///
|
||||
/// The default value is `false`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"background-image-repeat": bool = false,
|
||||
|
||||
/// The foreground and background color for selection. If this is not set, then
|
||||
@ -624,6 +650,8 @@ foreground: Color = .{ .r = 0xFF, .g = 0xFF, .b = 0xFF },
|
||||
///
|
||||
/// If this is `false`, then the selection can still be manually
|
||||
/// cleared by clicking once or by pressing `escape`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"selection-clear-on-typing": bool = true,
|
||||
|
||||
/// The minimum contrast ratio between the foreground and background colors.
|
||||
@ -661,11 +689,10 @@ palette: Palette = .{},
|
||||
/// other colors at runtime:
|
||||
///
|
||||
/// * `cell-foreground` - Match the cell foreground color.
|
||||
/// (Available since version 1.2.0)
|
||||
/// (Available since: 1.2.0)
|
||||
///
|
||||
/// * `cell-background` - Match the cell background color.
|
||||
/// (Available since version 1.2.0)
|
||||
///
|
||||
/// (Available since: 1.2.0)
|
||||
@"cursor-color": ?TerminalColor = null,
|
||||
|
||||
/// The opacity level (opposite of transparency) of the cursor. A value of 1
|
||||
@ -690,7 +717,6 @@ palette: Palette = .{},
|
||||
/// * `bar`
|
||||
/// * `underline`
|
||||
/// * `block_hollow`
|
||||
///
|
||||
@"cursor-style": terminal.CursorStyle = .block,
|
||||
|
||||
/// Sets the default blinking state of the cursor. This is just the default
|
||||
@ -710,7 +736,6 @@ palette: Palette = .{},
|
||||
/// * ` ` (blank)
|
||||
/// * `true`
|
||||
/// * `false`
|
||||
///
|
||||
@"cursor-style-blink": ?bool = null,
|
||||
|
||||
/// The color of the text under the cursor. If this is not set, a default will
|
||||
@ -767,7 +792,6 @@ palette: Palette = .{},
|
||||
/// * `false`
|
||||
/// * `always`
|
||||
/// * `never`
|
||||
///
|
||||
@"mouse-shift-capture": MouseShiftCapture = .false,
|
||||
|
||||
/// Multiplier for scrolling distance with the mouse wheel. Any value less
|
||||
@ -775,6 +799,8 @@ palette: Palette = .{},
|
||||
/// value.
|
||||
///
|
||||
/// A value of "3" (default) scrolls 3 lines per tick.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"mouse-scroll-multiplier": f64 = 3.0,
|
||||
|
||||
/// The opacity level (opposite of transparency) of the background. A value of
|
||||
@ -843,6 +869,8 @@ palette: Palette = .{},
|
||||
|
||||
/// The color of the split divider. If this is not set, a default will be chosen.
|
||||
/// Specified as either hex (`#RRGGBB` or `RRGGBB`) or a named X11 color.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"split-divider-color": ?Color = null,
|
||||
|
||||
/// The command to run, usually a shell. If this is not an absolute path, it'll
|
||||
@ -857,14 +885,14 @@ palette: Palette = .{},
|
||||
/// arguments are provided, the command will be executed using `/bin/sh -c`
|
||||
/// to offload shell argument expansion.
|
||||
///
|
||||
/// To avoid shell expansion altogether, prefix the command with `direct:`,
|
||||
/// e.g. `direct:nvim foo`. This will avoid the roundtrip to `/bin/sh` but will
|
||||
/// also not support any shell parsing such as arguments with spaces, filepaths
|
||||
/// with `~`, globs, etc.
|
||||
/// To avoid shell expansion altogether, prefix the command with `direct:`, e.g.
|
||||
/// `direct:nvim foo`. This will avoid the roundtrip to `/bin/sh` but will also
|
||||
/// not support any shell parsing such as arguments with spaces, filepaths with
|
||||
/// `~`, globs, etc. (Available since: 1.2.0)
|
||||
///
|
||||
/// You can also explicitly prefix the command with `shell:` to always
|
||||
/// wrap the command in a shell. This can be used to ensure our heuristics
|
||||
/// to choose the right mode are not used in case they are wrong.
|
||||
/// You can also explicitly prefix the command with `shell:` to always wrap the
|
||||
/// command in a shell. This can be used to ensure our heuristics to choose the
|
||||
/// right mode are not used in case they are wrong. (Available since: 1.2.0)
|
||||
///
|
||||
/// This command will be used for all new terminal surfaces, i.e. new windows,
|
||||
/// tabs, etc. If you want to run a command only for the first terminal surface
|
||||
@ -910,7 +938,6 @@ command: ?Command = null,
|
||||
/// shell integration with a `-e`-executed command, you must either
|
||||
/// name your binary appropriately or source the shell integration script
|
||||
/// manually.
|
||||
///
|
||||
@"initial-command": ?Command = null,
|
||||
|
||||
/// Extra environment variables to pass to commands launched in a terminal
|
||||
@ -947,6 +974,8 @@ command: ?Command = null,
|
||||
/// These environment variables _will not_ be passed to commands run by Ghostty
|
||||
/// for other purposes, like `open` or `xdg-open` used to open URLs in your
|
||||
/// browser.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
env: RepeatableStringMap = .{},
|
||||
|
||||
/// Data to send as input to the command on startup.
|
||||
@ -988,6 +1017,8 @@ env: RepeatableStringMap = .{},
|
||||
///
|
||||
/// Changing this configuration at runtime will only affect new
|
||||
/// terminals.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
input: RepeatableReadableIO = .{},
|
||||
|
||||
/// If true, keep the terminal open after the command exits. Normally, the
|
||||
@ -1056,11 +1087,15 @@ link: RepeatableLink = .{},
|
||||
/// previews are never shown. When set to "osc8", link previews are only shown
|
||||
/// for hyperlinks created with the OSC 8 sequence (in this case, the link text
|
||||
/// can differ from the link destination).
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"link-previews": LinkPreviews = .true,
|
||||
|
||||
/// Whether to start the window in a maximized state. This setting applies
|
||||
/// to new windows and does not apply to tabs, splits, etc. However, this setting
|
||||
/// will apply to all new windows, not just the first one.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
maximize: bool = false,
|
||||
|
||||
/// Start new windows in fullscreen. This setting applies to new windows and
|
||||
@ -1285,6 +1320,8 @@ class: ?[:0]const u8 = null,
|
||||
/// applies to actions that are surface-specific. For actions that
|
||||
/// are already global (e.g. `quit`), this prefix has no effect.
|
||||
///
|
||||
/// Available since: 1.0.0
|
||||
///
|
||||
/// * `global:` - Make the keybind global. By default, keybinds only work
|
||||
/// within Ghostty and under the right conditions (application focused,
|
||||
/// sometimes terminal focused, etc.). If you want a keybind to work
|
||||
@ -1293,6 +1330,9 @@ class: ?[:0]const u8 = null,
|
||||
/// work in all environments; see the additional notes below for more
|
||||
/// information.
|
||||
///
|
||||
/// Available since: 1.0.0 (on macOS)
|
||||
/// Available since: 1.2.0 (on GTK)
|
||||
///
|
||||
/// * `unconsumed:` - Do not consume the input. By default, a keybind
|
||||
/// will consume the input, meaning that the associated encoding (if
|
||||
/// any) will not be sent to the running program in the terminal. If
|
||||
@ -1303,6 +1343,8 @@ class: ?[:0]const u8 = null,
|
||||
/// Since they are not associated with a specific terminal surface,
|
||||
/// they're never encoded.
|
||||
///
|
||||
/// Available since: 1.0.0
|
||||
///
|
||||
/// * `performable:` - Only consume the input if the action is able to be
|
||||
/// performed. For example, the `copy_to_clipboard` action will only
|
||||
/// consume the input if there is a selection to copy. If there is no
|
||||
@ -1318,6 +1360,8 @@ class: ?[:0]const u8 = null,
|
||||
/// Performable keybinds will still work, they just won't appear as
|
||||
/// a shortcut label in the menu.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
///
|
||||
/// Keybind triggers are not unique per prefix combination. For example,
|
||||
/// `ctrl+a` and `global:ctrl+a` are not two separate keybinds. The keybind
|
||||
/// set later will overwrite the keybind set earlier. In this case, the
|
||||
@ -1427,7 +1471,6 @@ keybind: Keybinds = .{},
|
||||
/// do not look good extended.
|
||||
/// * The nearest row contains a perfect fit powerline character. These
|
||||
/// don't look good extended.
|
||||
///
|
||||
@"window-padding-color": WindowPaddingColor = .background,
|
||||
|
||||
/// Synchronize rendering with the screen refresh rate. If true, this will
|
||||
@ -1474,6 +1517,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// * `client` - Prefer client-side decorations.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
///
|
||||
/// * `server` - Prefer server-side decorations. This is only relevant
|
||||
/// on Linux with GTK, either on X11, or Wayland on a compositor that
|
||||
/// supports the `org_kde_kwin_server_decoration` protocol (e.g. KDE Plasma,
|
||||
@ -1482,6 +1527,8 @@ keybind: Keybinds = .{},
|
||||
/// If `server` is set but the environment doesn't support server-side
|
||||
/// decorations, client-side decorations will be used instead.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
///
|
||||
/// The default value is `auto`.
|
||||
///
|
||||
/// For the sake of backwards compatibility and convenience, this setting also
|
||||
@ -1504,6 +1551,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Note: any font available on the system may be used, this font is not
|
||||
/// required to be a fixed-width font.
|
||||
///
|
||||
/// Available since: 1.1.0 (on GTK)
|
||||
@"window-title-font-family": ?[:0]const u8 = null,
|
||||
|
||||
/// The text that will be displayed in the subtitle of the window. Valid values:
|
||||
@ -1513,6 +1562,8 @@ keybind: Keybinds = .{},
|
||||
/// surface.
|
||||
///
|
||||
/// This feature is only supported on GTK.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"window-subtitle": WindowSubtitle = .false,
|
||||
|
||||
/// The theme to use for the windows. Valid values:
|
||||
@ -1656,6 +1707,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Always display the tab bar, even when there's only one tab.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
///
|
||||
/// - `auto` *(default)*
|
||||
///
|
||||
/// Automatically show and hide the tab bar. The tab bar is only
|
||||
@ -1740,6 +1793,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// The maximum value is `584y 49w 23h 34m 33s 709ms 551µs 615ns`. Any
|
||||
/// value larger than this will be clamped to the maximum value.
|
||||
///
|
||||
/// Available since 1.0.0
|
||||
@"resize-overlay-duration": Duration = .{ .duration = 750 * std.time.ns_per_ms },
|
||||
|
||||
/// If true, when there are multiple split panes, the mouse selects the pane
|
||||
@ -1785,6 +1840,8 @@ keybind: Keybinds = .{},
|
||||
/// Warning: This can expose sensitive information at best and enable
|
||||
/// arbitrary code execution at worst (with a maliciously crafted title
|
||||
/// and a minor amount of user interaction).
|
||||
///
|
||||
/// Available since: 1.0.1
|
||||
@"title-report": bool = false,
|
||||
|
||||
/// The total amount of bytes that can be used for image data (e.g. the Kitty
|
||||
@ -1972,6 +2029,8 @@ keybind: Keybinds = .{},
|
||||
/// This configuration is only supported on macOS. Linux doesn't
|
||||
/// support undo operations at all so this configuration has no
|
||||
/// effect.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"undo-timeout": Duration = .{ .duration = 5 * std.time.ns_per_s },
|
||||
|
||||
/// The position of the "quick" terminal window. To learn more about the
|
||||
@ -2075,6 +2134,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Only implemented on macOS.
|
||||
/// On Linux the behavior is always equivalent to `move`.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"quick-terminal-space-behavior": QuickTerminalSpaceBehavior = .move,
|
||||
|
||||
/// Determines under which circumstances that the quick terminal should receive
|
||||
@ -2103,6 +2164,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Only has an effect on Linux Wayland.
|
||||
/// On macOS the behavior is always equivalent to `on-demand`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"quick-terminal-keyboard-interactivity": QuickTerminalKeyboardInteractivity = .@"on-demand",
|
||||
|
||||
/// Whether to enable shell integration auto-injection or not. Shell integration
|
||||
@ -2139,6 +2202,8 @@ keybind: Keybinds = .{},
|
||||
/// its default value is used, so you must explicitly disable features you don't
|
||||
/// want. You can also use `true` or `false` to turn all features on or off.
|
||||
///
|
||||
/// Example: `cursor`, `no-cursor`, `sudo`, `no-sudo`, `title`, `no-title`
|
||||
///
|
||||
/// Available features:
|
||||
///
|
||||
/// * `cursor` - Set the cursor to a blinking bar at the prompt.
|
||||
@ -2147,7 +2212,26 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// * `title` - Set the window title via shell integration.
|
||||
///
|
||||
/// Example: `cursor`, `no-cursor`, `sudo`, `no-sudo`, `title`, `no-title`
|
||||
/// * `ssh-env` - Enable SSH environment variable compatibility. Automatically
|
||||
/// converts TERM from `xterm-ghostty` to `xterm-256color` when connecting to
|
||||
/// remote hosts and propagates COLORTERM, TERM_PROGRAM, and TERM_PROGRAM_VERSION.
|
||||
/// Whether or not these variables will be accepted by the remote host(s) will
|
||||
/// depend on whether or not the variables are allowed in their sshd_config.
|
||||
/// (Available since: 1.2.0)
|
||||
///
|
||||
/// * `ssh-terminfo` - Enable automatic terminfo installation on remote hosts.
|
||||
/// Attempts to install Ghostty's terminfo entry using `infocmp` and `tic` when
|
||||
/// connecting to hosts that lack it. Requires `infocmp` to be available locally
|
||||
/// and `tic` to be available on remote hosts. Once terminfo is installed on a
|
||||
/// remote host, it will be automatically "cached" to avoid repeat installations.
|
||||
/// If desired, the `+ssh-cache` CLI action can be used to manage the installation
|
||||
/// cache manually using various arguments.
|
||||
/// (Available since: 1.2.0)
|
||||
///
|
||||
/// SSH features work independently and can be combined for optimal experience:
|
||||
/// when both `ssh-env` and `ssh-terminfo` are enabled, Ghostty will install its
|
||||
/// terminfo on remote hosts and use `xterm-ghostty` as TERM, falling back to
|
||||
/// `xterm-256color` with environment variables if terminfo installation fails.
|
||||
@"shell-integration-features": ShellIntegrationFeatures = .{},
|
||||
|
||||
/// Custom entries into the command palette.
|
||||
@ -2170,6 +2254,8 @@ keybind: Keybinds = .{},
|
||||
/// ```ini
|
||||
/// command-palette-entry =
|
||||
/// ```
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"command-palette-entry": RepeatableCommand = .{},
|
||||
|
||||
/// Sets the reporting format for OSC sequences that request color information.
|
||||
@ -2334,6 +2420,8 @@ keybind: Keybinds = .{},
|
||||
/// Only implemented on macOS.
|
||||
///
|
||||
/// Example: `audio`, `no-audio`, `system`, `no-system`
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"bell-features": BellFeatures = .{},
|
||||
|
||||
/// If `audio` is an enabled bell feature, this is a path to an audio file. If
|
||||
@ -2341,12 +2429,16 @@ keybind: Keybinds = .{},
|
||||
/// configuration file that it is referenced from, or from the current working
|
||||
/// directory if this is used as a CLI flag. The path may be prefixed with `~/`
|
||||
/// to reference the user's home directory. (GTK only)
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"bell-audio-path": ?Path = null,
|
||||
|
||||
/// If `audio` is an enabled bell feature, this is the volume to play the audio
|
||||
/// file at (relative to the system volume). This is a floating point number
|
||||
/// ranging from 0.0 (silence) to 1.0 (as loud as possible). The default is 0.5.
|
||||
/// (GTK only)
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"bell-audio-volume": f64 = 0.5,
|
||||
|
||||
/// Control the in-app notifications that Ghostty shows.
|
||||
@ -2372,6 +2464,8 @@ keybind: Keybinds = .{},
|
||||
/// enable all notifications.
|
||||
///
|
||||
/// This configuration only applies to GTK.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"app-notifications": AppNotifications = .{},
|
||||
|
||||
/// If anything other than false, fullscreen mode on macOS will not use the
|
||||
@ -2422,6 +2516,8 @@ keybind: Keybinds = .{},
|
||||
/// The default value is `visible`.
|
||||
///
|
||||
/// Changing this option at runtime only applies to new windows.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"macos-window-buttons": MacWindowButtons = .visible,
|
||||
|
||||
/// The style of the macOS titlebar. Available values are: "native",
|
||||
@ -2544,6 +2640,8 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Note: When the macOS application is hidden, keyboard layout changes
|
||||
/// will no longer be automatic. This is a limitation of macOS.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"macos-hidden": MacHidden = .never,
|
||||
|
||||
/// If true, Ghostty on macOS will automatically enable the "Secure Input"
|
||||
@ -2605,7 +2703,6 @@ keybind: Keybinds = .{},
|
||||
/// This is because the update dialog is managed through a
|
||||
/// separate framework and cannot be customized without significant
|
||||
/// effort.
|
||||
///
|
||||
@"macos-icon": MacAppIcon = .official,
|
||||
|
||||
/// The material to use for the frame of the macOS app icon.
|
||||
@ -2619,7 +2716,6 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Note: This configuration is required when `macos-icon` is set to
|
||||
/// `custom-style`.
|
||||
///
|
||||
@"macos-icon-frame": MacAppIconFrame = .aluminum,
|
||||
|
||||
/// The color of the ghost in the macOS app icon.
|
||||
@ -2640,7 +2736,6 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// Note: This configuration is required when `macos-icon` is set to
|
||||
/// `custom-style`.
|
||||
///
|
||||
@"macos-icon-screen-color": ?ColorList = null,
|
||||
|
||||
/// Whether macOS Shortcuts are allowed to control Ghostty.
|
||||
@ -2664,6 +2759,7 @@ keybind: Keybinds = .{},
|
||||
///
|
||||
/// * `deny` - Deny Shortcuts from controlling Ghostty.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"macos-shortcuts": MacShortcuts = .ask,
|
||||
|
||||
/// Put every surface (tab, split, window) into a dedicated Linux cgroup.
|
||||
@ -2691,7 +2787,6 @@ keybind: Keybinds = .{},
|
||||
/// * `always` - Always use cgroups.
|
||||
/// * `single-instance` - Enable cgroups only for Ghostty instances launched
|
||||
/// as single-instance applications (see gtk-single-instance).
|
||||
///
|
||||
@"linux-cgroup": LinuxCgroup = if (builtin.os.tag == .linux)
|
||||
.@"single-instance"
|
||||
else
|
||||
@ -2728,6 +2823,8 @@ else
|
||||
|
||||
/// Enable or disable GTK's OpenGL debugging logs. The default is `true` for
|
||||
/// debug builds, `false` for all others.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"gtk-opengl-debug": bool = builtin.mode == .Debug,
|
||||
|
||||
/// If `true`, the Ghostty GTK application will run in single-instance mode:
|
||||
@ -2765,6 +2862,8 @@ else
|
||||
|
||||
/// If this is `true`, the titlebar will be hidden when the window is maximized,
|
||||
/// and shown when the titlebar is unmaximized. GTK only.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"gtk-titlebar-hide-when-maximized": bool = false,
|
||||
|
||||
/// Determines the appearance of the top and bottom bars tab bar.
|
||||
@ -2802,6 +2901,8 @@ else
|
||||
/// not exist. If you want to include a file that begins with a literal ?
|
||||
/// character, surround the file path in double quotes (").
|
||||
/// The file size limit for a single stylesheet is 5MiB.
|
||||
///
|
||||
/// Available since: 1.1.0
|
||||
@"gtk-custom-css": RepeatablePath = .{},
|
||||
|
||||
/// If `true` (default), applications running in the terminal can show desktop
|
||||
@ -2813,8 +2914,8 @@ else
|
||||
/// This can be set to a specific color, using the same format as
|
||||
/// `background` or `foreground` (e.g. `#RRGGBB` but other formats
|
||||
/// are also supported; see the aforementioned documentation). If a
|
||||
/// specific color is set, this color will always be used for all
|
||||
/// bold text regardless of the terminal's color scheme.
|
||||
/// specific color is set, this color will always be used for the default
|
||||
/// bold text color. It will set the rest of the bold colors to `bright`.
|
||||
///
|
||||
/// This can also be set to `bright`, which uses the bright color palette
|
||||
/// for bold text. For example, if the text is red, then the bold will
|
||||
@ -2854,6 +2955,8 @@ term: []const u8 = "xterm-ghostty",
|
||||
/// this isn't intended to be modified by users, the documentation is
|
||||
/// lighter than the other configurations and users are expected to
|
||||
/// refer to the code for details.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"launched-from": ?LaunchSource = null,
|
||||
|
||||
/// Configures the low-level API to use for async IO, eventing, etc.
|
||||
@ -2882,6 +2985,8 @@ term: []const u8 = "xterm-ghostty",
|
||||
///
|
||||
/// This is only supported on Linux, since this is the only platform
|
||||
/// where we have multiple options. On macOS, we always use `kqueue`.
|
||||
///
|
||||
/// Available since: 1.2.0
|
||||
@"async-backend": AsyncBackend = .auto,
|
||||
|
||||
/// Control the auto-update functionality of Ghostty. This is only supported
|
||||
@ -6552,6 +6657,8 @@ pub const ShellIntegrationFeatures = packed struct {
|
||||
cursor: bool = true,
|
||||
sudo: bool = false,
|
||||
title: bool = true,
|
||||
@"ssh-env": bool = false,
|
||||
@"ssh-terminfo": bool = false,
|
||||
};
|
||||
|
||||
pub const RepeatableCommand = struct {
|
||||
|
@ -5,18 +5,19 @@ const Allocator = std.mem.Allocator;
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const internal_os = @import("../os/main.zig");
|
||||
|
||||
/// Open the configuration in the OS default editor according to the default
|
||||
/// paths the main config file could be in.
|
||||
/// The path to the configuration that should be opened for editing.
|
||||
///
|
||||
/// On Linux, this will open the file at the XDG config path. This is the
|
||||
/// On Linux, this will use the file at the XDG config path. This is the
|
||||
/// only valid path for Linux so we don't need to check for other paths.
|
||||
///
|
||||
/// On macOS, both XDG and AppSupport paths are valid. Because Ghostty
|
||||
/// prioritizes AppSupport over XDG, we will open AppSupport if it exists,
|
||||
/// prioritizes AppSupport over XDG, we will use AppSupport if it exists,
|
||||
/// followed by XDG if it exists, and finally AppSupport if neither exist.
|
||||
/// For the existence check, we also prefer non-empty files over empty
|
||||
/// files.
|
||||
pub fn open(alloc_gpa: Allocator) !void {
|
||||
///
|
||||
/// The returned value is allocated using the provided allocator.
|
||||
pub fn openPath(alloc_gpa: Allocator) ![:0]const u8 {
|
||||
// Use an arena to make memory management easier in here.
|
||||
var arena = ArenaAllocator.init(alloc_gpa);
|
||||
defer arena.deinit();
|
||||
@ -41,7 +42,7 @@ pub fn open(alloc_gpa: Allocator) !void {
|
||||
}
|
||||
};
|
||||
|
||||
try internal_os.open(alloc_gpa, .text, config_path);
|
||||
return try alloc_gpa.dupeZ(u8, config_path);
|
||||
}
|
||||
|
||||
/// Returns the config path to use for open for the current OS.
|
||||
|
@ -69,10 +69,14 @@ pub fn deinit(self: *Collection, alloc: Allocator) void {
|
||||
if (self.load_options) |*v| v.deinit(alloc);
|
||||
}
|
||||
|
||||
pub const AddError = Allocator.Error || error{
|
||||
CollectionFull,
|
||||
DeferredLoadingUnavailable,
|
||||
};
|
||||
pub const AddError =
|
||||
Allocator.Error ||
|
||||
AdjustSizeError ||
|
||||
error{
|
||||
CollectionFull,
|
||||
DeferredLoadingUnavailable,
|
||||
SetSizeFailed,
|
||||
};
|
||||
|
||||
/// Add a face to the collection for the given style. This face will be added
|
||||
/// next in priority if others exist already, i.e. it'll be the _last_ to be
|
||||
@ -81,10 +85,9 @@ pub const AddError = Allocator.Error || error{
|
||||
/// If no error is encountered then the collection takes ownership of the face,
|
||||
/// in which case face will be deallocated when the collection is deallocated.
|
||||
///
|
||||
/// If a loaded face is added to the collection, it should be the same
|
||||
/// size as all the other faces in the collection. This function will not
|
||||
/// verify or modify the size until the size of the entire collection is
|
||||
/// changed.
|
||||
/// If a loaded face is added to the collection, its size will be changed to
|
||||
/// match the size specified in load_options, adjusted for harmonization with
|
||||
/// the primary face.
|
||||
pub fn add(
|
||||
self: *Collection,
|
||||
alloc: Allocator,
|
||||
@ -103,9 +106,107 @@ pub fn add(
|
||||
return error.DeferredLoadingUnavailable;
|
||||
|
||||
try list.append(alloc, face);
|
||||
|
||||
var owned: *Entry = list.at(idx);
|
||||
|
||||
// If the face is already loaded, apply font size adjustment
|
||||
// now, otherwise we'll apply it whenever we do load it.
|
||||
if (owned.getLoaded()) |loaded| {
|
||||
if (try self.adjustedSize(loaded)) |opts| {
|
||||
loaded.setSize(opts.faceOptions()) catch return error.SetSizeFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return .{ .style = style, .idx = @intCast(idx) };
|
||||
}
|
||||
|
||||
pub const AdjustSizeError = font.Face.GetMetricsError;
|
||||
|
||||
// Calculate a size for the provided face that will match it with the primary
|
||||
// font, metrically, to improve consistency with fallback fonts. Right now we
|
||||
// match the font based on the ex height, or the ideograph width if the font
|
||||
// has ideographs in it.
|
||||
//
|
||||
// This returns null if load options is null or if self.load_options is null.
|
||||
//
|
||||
// This is very much like the `font-size-adjust` CSS property in how it works.
|
||||
// ref: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size-adjust
|
||||
//
|
||||
// TODO: In the future, provide config options that allow the user to select
|
||||
// which metric should be matched for fallback fonts, instead of hard
|
||||
// coding it as ex height.
|
||||
pub fn adjustedSize(
|
||||
self: *Collection,
|
||||
face: *Face,
|
||||
) AdjustSizeError!?LoadOptions {
|
||||
const load_options = self.load_options orelse return null;
|
||||
|
||||
// We silently do nothing if we can't get the primary
|
||||
// face, because this might be the primary face itself.
|
||||
const primary_face = self.getFace(.{ .idx = 0 }) catch return null;
|
||||
|
||||
// We do nothing if the primary face and this face are the same.
|
||||
if (@intFromPtr(primary_face) == @intFromPtr(face)) return null;
|
||||
|
||||
const primary_metrics = try primary_face.getMetrics();
|
||||
const face_metrics = try face.getMetrics();
|
||||
|
||||
// We use the ex height to match our font sizes, so that the height of
|
||||
// lower-case letters matches between all fonts in the fallback chain.
|
||||
//
|
||||
// We estimate ex height as 0.75 * cap height if it's not specifically
|
||||
// provided, and we estimate cap height as 0.75 * ascent in the same case.
|
||||
//
|
||||
// If the fallback font has an ic_width we prefer that, for normalization
|
||||
// of CJK font sizes when mixed with latin fonts.
|
||||
//
|
||||
// We estimate the ic_width as twice the cell width if it isn't provided.
|
||||
var primary_cap = primary_metrics.cap_height orelse 0.0;
|
||||
if (primary_cap <= 0) primary_cap = primary_metrics.ascent * 0.75;
|
||||
|
||||
var primary_ex = primary_metrics.ex_height orelse 0.0;
|
||||
if (primary_ex <= 0) primary_ex = primary_cap * 0.75;
|
||||
|
||||
var primary_ic = primary_metrics.ic_width orelse 0.0;
|
||||
if (primary_ic <= 0) primary_ic = primary_metrics.cell_width * 2;
|
||||
|
||||
var face_cap = face_metrics.cap_height orelse 0.0;
|
||||
if (face_cap <= 0) face_cap = face_metrics.ascent * 0.75;
|
||||
|
||||
var face_ex = face_metrics.ex_height orelse 0.0;
|
||||
if (face_ex <= 0) face_ex = face_cap * 0.75;
|
||||
|
||||
var face_ic = face_metrics.ic_width orelse 0.0;
|
||||
if (face_ic <= 0) face_ic = face_metrics.cell_width * 2;
|
||||
|
||||
// If the line height of the scaled font would be larger than
|
||||
// the line height of the primary font, we don't want that, so
|
||||
// we take the minimum between matching the ic/ex and the line
|
||||
// height.
|
||||
//
|
||||
// NOTE: We actually allow the line height to be up to 1.2
|
||||
// times the primary line height because empirically
|
||||
// this is usually fine and is better for CJK.
|
||||
//
|
||||
// TODO: We should probably provide a config option that lets
|
||||
// the user pick what metric to use for size adjustment.
|
||||
const scale = @min(
|
||||
1.2 * primary_metrics.lineHeight() / face_metrics.lineHeight(),
|
||||
if (face_metrics.ic_width != null)
|
||||
primary_ic / face_ic
|
||||
else
|
||||
primary_ex / face_ex,
|
||||
);
|
||||
|
||||
// Make a copy of our load options, set the size to the size of
|
||||
// the provided face, and then multiply that by our scaling factor.
|
||||
var opts = load_options;
|
||||
opts.size = face.size;
|
||||
opts.size.points *= @as(f32, @floatCast(scale));
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
/// Return the Face represented by a given Index. The returned pointer
|
||||
/// is only valid as long as this collection is not modified.
|
||||
///
|
||||
@ -129,21 +230,38 @@ pub fn getFace(self: *Collection, index: Index) !*Face {
|
||||
break :item item;
|
||||
};
|
||||
|
||||
return try self.getFaceFromEntry(item);
|
||||
const face = try self.getFaceFromEntry(
|
||||
item,
|
||||
// We only want to adjust the size if this isn't the primary face.
|
||||
index.style != .regular or index.idx > 0,
|
||||
);
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
/// Get the face from an entry.
|
||||
///
|
||||
/// This entry must not be an alias.
|
||||
fn getFaceFromEntry(self: *Collection, entry: *Entry) !*Face {
|
||||
fn getFaceFromEntry(
|
||||
self: *Collection,
|
||||
entry: *Entry,
|
||||
/// Whether to adjust the font size to match the primary face after loading.
|
||||
adjust: bool,
|
||||
) !*Face {
|
||||
assert(entry.* != .alias);
|
||||
|
||||
return switch (entry.*) {
|
||||
inline .deferred, .fallback_deferred => |*d, tag| deferred: {
|
||||
const opts = self.load_options orelse
|
||||
return error.DeferredLoadingUnavailable;
|
||||
const face = try d.load(opts.library, opts.faceOptions());
|
||||
var face = try d.load(opts.library, opts.faceOptions());
|
||||
d.deinit();
|
||||
|
||||
// If we need to adjust the size, do so.
|
||||
if (adjust) if (try self.adjustedSize(&face)) |new_opts| {
|
||||
try face.setSize(new_opts.faceOptions());
|
||||
};
|
||||
|
||||
entry.* = switch (tag) {
|
||||
.deferred => .{ .loaded = face },
|
||||
.fallback_deferred => .{ .fallback_loaded = face },
|
||||
@ -247,7 +365,7 @@ pub fn completeStyles(
|
||||
while (it.next()) |entry| {
|
||||
// Load our face. If we fail to load it, we just skip it and
|
||||
// continue on to try the next one.
|
||||
const face = self.getFaceFromEntry(entry) catch |err| {
|
||||
const face = self.getFaceFromEntry(entry, false) catch |err| {
|
||||
log.warn("error loading regular entry={d} err={}", .{
|
||||
it.index - 1,
|
||||
err,
|
||||
@ -371,7 +489,7 @@ fn syntheticBold(self: *Collection, entry: *Entry) !Face {
|
||||
const opts = self.load_options orelse return error.DeferredLoadingUnavailable;
|
||||
|
||||
// Try to bold it.
|
||||
const regular = try self.getFaceFromEntry(entry);
|
||||
const regular = try self.getFaceFromEntry(entry, false);
|
||||
const face = try regular.syntheticBold(opts.faceOptions());
|
||||
|
||||
var buf: [256]u8 = undefined;
|
||||
@ -391,7 +509,7 @@ fn syntheticItalic(self: *Collection, entry: *Entry) !Face {
|
||||
const opts = self.load_options orelse return error.DeferredLoadingUnavailable;
|
||||
|
||||
// Try to italicize it.
|
||||
const regular = try self.getFaceFromEntry(entry);
|
||||
const regular = try self.getFaceFromEntry(entry, false);
|
||||
const face = try regular.syntheticItalic(opts.faceOptions());
|
||||
|
||||
var buf: [256]u8 = undefined;
|
||||
@ -420,9 +538,12 @@ pub fn setSize(self: *Collection, size: DesiredSize) !void {
|
||||
while (it.next()) |array| {
|
||||
var entry_it = array.value.iterator(0);
|
||||
while (entry_it.next()) |entry| switch (entry.*) {
|
||||
.loaded, .fallback_loaded => |*f| try f.setSize(
|
||||
opts.faceOptions(),
|
||||
),
|
||||
.loaded,
|
||||
.fallback_loaded,
|
||||
=> |*f| {
|
||||
const new_opts = try self.adjustedSize(f) orelse opts.*;
|
||||
try f.setSize(new_opts.faceOptions());
|
||||
},
|
||||
|
||||
// Deferred aren't loaded so we don't need to set their size.
|
||||
// The size for when they're loaded is set since `opts` changed.
|
||||
@ -549,6 +670,16 @@ pub const Entry = union(enum) {
|
||||
}
|
||||
}
|
||||
|
||||
/// If this face is loaded, or is an alias to a loaded face,
|
||||
/// then this returns the `Face`, otherwise returns null.
|
||||
pub fn getLoaded(self: *Entry) ?*Face {
|
||||
return switch (self.*) {
|
||||
.deferred, .fallback_deferred => null,
|
||||
.loaded, .fallback_loaded => |*face| face,
|
||||
.alias => |v| v.getLoaded(),
|
||||
};
|
||||
}
|
||||
|
||||
/// True if the entry is deferred.
|
||||
fn isDeferred(self: Entry) bool {
|
||||
return switch (self) {
|
||||
@ -906,12 +1037,13 @@ test "metrics" {
|
||||
|
||||
var c = init();
|
||||
defer c.deinit(alloc);
|
||||
c.load_options = .{ .library = lib };
|
||||
const size: DesiredSize = .{ .points = 12, .xdpi = 96, .ydpi = 96 };
|
||||
c.load_options = .{ .library = lib, .size = size };
|
||||
|
||||
_ = try c.add(alloc, .regular, .{ .loaded = try .init(
|
||||
lib,
|
||||
testFont,
|
||||
.{ .size = .{ .points = 12, .xdpi = 96, .ydpi = 96 } },
|
||||
.{ .size = size },
|
||||
) });
|
||||
|
||||
try c.updateMetrics();
|
||||
@ -940,6 +1072,7 @@ test "metrics" {
|
||||
.overline_thickness = 1,
|
||||
.box_thickness = 1,
|
||||
.cursor_height = 17,
|
||||
.icon_height = 11,
|
||||
}, c.metrics);
|
||||
|
||||
// Resize should change metrics
|
||||
@ -956,5 +1089,65 @@ test "metrics" {
|
||||
.overline_thickness = 2,
|
||||
.box_thickness = 2,
|
||||
.cursor_height = 34,
|
||||
.icon_height = 23,
|
||||
}, c.metrics);
|
||||
}
|
||||
|
||||
// TODO: Also test CJK fallback sizing, we don't currently have a CJK test font.
|
||||
test "adjusted sizes" {
|
||||
const testing = std.testing;
|
||||
const alloc = testing.allocator;
|
||||
const testFont = font.embedded.inconsolata;
|
||||
const fallback = font.embedded.monaspace_neon;
|
||||
|
||||
var lib = try Library.init(alloc);
|
||||
defer lib.deinit();
|
||||
|
||||
var c = init();
|
||||
defer c.deinit(alloc);
|
||||
const size: DesiredSize = .{ .points = 12, .xdpi = 96, .ydpi = 96 };
|
||||
c.load_options = .{ .library = lib, .size = size };
|
||||
|
||||
// Add our primary face.
|
||||
_ = try c.add(alloc, .regular, .{ .loaded = try .init(
|
||||
lib,
|
||||
testFont,
|
||||
.{ .size = size },
|
||||
) });
|
||||
|
||||
try c.updateMetrics();
|
||||
|
||||
// Add the fallback face.
|
||||
const fallback_idx = try c.add(alloc, .regular, .{ .loaded = try .init(
|
||||
lib,
|
||||
fallback,
|
||||
.{ .size = size },
|
||||
) });
|
||||
|
||||
// The ex heights should match.
|
||||
{
|
||||
const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
|
||||
const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
|
||||
|
||||
try std.testing.expectApproxEqAbs(
|
||||
primary_metrics.ex_height.?,
|
||||
fallback_metrics.ex_height.?,
|
||||
// We accept anything within half a pixel.
|
||||
0.5,
|
||||
);
|
||||
}
|
||||
|
||||
// Resize should keep that relationship.
|
||||
try c.setSize(.{ .points = 37, .xdpi = 96, .ydpi = 96 });
|
||||
{
|
||||
const primary_metrics = try (try c.getFace(.{ .idx = 0 })).getMetrics();
|
||||
const fallback_metrics = try (try c.getFace(fallback_idx)).getMetrics();
|
||||
|
||||
try std.testing.expectApproxEqAbs(
|
||||
primary_metrics.ex_height.?,
|
||||
fallback_metrics.ex_height.?,
|
||||
// We accept anything within half a pixel.
|
||||
0.5,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,3 @@ offset_y: i32,
|
||||
/// be normalized to be between 0 and 1 prior to use in shaders.
|
||||
atlas_x: u32,
|
||||
atlas_y: u32,
|
||||
|
||||
/// horizontal position to increase drawing position for strings
|
||||
advance_x: f32,
|
||||
|
||||
/// Whether we drew this glyph ourselves with the sprite font.
|
||||
sprite: bool = false,
|
||||
|
@ -35,9 +35,8 @@ cursor_thickness: u32 = 1,
|
||||
/// The height in pixels of the cursor sprite.
|
||||
cursor_height: u32,
|
||||
|
||||
/// Original cell width in pixels. This is used to keep
|
||||
/// glyphs centered if the cell width is adjusted wider.
|
||||
original_cell_width: ?u32 = null,
|
||||
/// The constraint height for nerd fonts icons.
|
||||
icon_height: u32,
|
||||
|
||||
/// Minimum acceptable values for some fields to prevent modifiers
|
||||
/// from being able to, for example, cause 0-thickness underlines.
|
||||
@ -50,6 +49,7 @@ const Minimums = struct {
|
||||
const box_thickness = 1;
|
||||
const cursor_thickness = 1;
|
||||
const cursor_height = 1;
|
||||
const icon_height = 1;
|
||||
};
|
||||
|
||||
/// Metrics extracted from a font face, based on
|
||||
@ -107,6 +107,19 @@ pub const FaceMetrics = struct {
|
||||
/// a provided ex height metric or measured from the height of the
|
||||
/// lowercase x glyph.
|
||||
ex_height: ?f64 = null,
|
||||
|
||||
/// The width of the character "水" (CJK water ideograph, U+6C34),
|
||||
/// if present. This is used for font size adjustment, to normalize
|
||||
/// the width of CJK fonts mixed with latin fonts.
|
||||
///
|
||||
/// NOTE: IC = Ideograph Character
|
||||
ic_width: ?f64 = null,
|
||||
|
||||
/// Convenience function for getting the line height
|
||||
/// (ascent - descent + line_gap).
|
||||
pub inline fn lineHeight(self: FaceMetrics) f64 {
|
||||
return self.ascent - self.descent + self.line_gap;
|
||||
}
|
||||
};
|
||||
|
||||
/// Calculate our metrics based on values extracted from a font.
|
||||
@ -120,7 +133,7 @@ pub fn calc(face: FaceMetrics) Metrics {
|
||||
// that the cell is large enough for the provided size, since we cast
|
||||
// it to an integer later.
|
||||
const cell_width = @ceil(face.cell_width);
|
||||
const cell_height = @ceil(face.ascent - face.descent + face.line_gap);
|
||||
const cell_height = @ceil(face.lineHeight());
|
||||
|
||||
// We split our line gap in two parts, and put half of it on the top
|
||||
// of the cell and the other half on the bottom, so that our text never
|
||||
@ -164,6 +177,17 @@ pub fn calc(face: FaceMetrics) Metrics {
|
||||
(face.strikethrough_position orelse
|
||||
ex_height * 0.5 + strikethrough_thickness * 0.5));
|
||||
|
||||
// The calculation for icon height in the nerd fonts patcher
|
||||
// is two thirds cap height to one third line height, but we
|
||||
// use an opinionated default of 1.2 * cap height instead.
|
||||
//
|
||||
// Doing this prevents fonts with very large line heights
|
||||
// from having excessively oversized icons, and allows fonts
|
||||
// with very small line heights to still have roomy icons.
|
||||
//
|
||||
// We do cap it at `cell_height` though for obvious reasons.
|
||||
const icon_height = @min(cell_height, cap_height * 1.2);
|
||||
|
||||
var result: Metrics = .{
|
||||
.cell_width = @intFromFloat(cell_width),
|
||||
.cell_height = @intFromFloat(cell_height),
|
||||
@ -176,6 +200,7 @@ pub fn calc(face: FaceMetrics) Metrics {
|
||||
.overline_thickness = @intFromFloat(underline_thickness),
|
||||
.box_thickness = @intFromFloat(underline_thickness),
|
||||
.cursor_height = @intFromFloat(cell_height),
|
||||
.icon_height = @intFromFloat(icon_height),
|
||||
};
|
||||
|
||||
// Ensure all metrics are within their allowable range.
|
||||
@ -201,11 +226,6 @@ pub fn apply(self: *Metrics, mods: ModifierSet) void {
|
||||
const new = @max(entry.value_ptr.apply(original), 1);
|
||||
if (new == original) continue;
|
||||
|
||||
// Preserve the original cell width if not set.
|
||||
if (self.original_cell_width == null) {
|
||||
self.original_cell_width = self.cell_width;
|
||||
}
|
||||
|
||||
// Set the new value
|
||||
@field(self, @tagName(tag)) = new;
|
||||
|
||||
@ -419,6 +439,7 @@ fn init() Metrics {
|
||||
.overline_thickness = 0,
|
||||
.box_thickness = 0,
|
||||
.cursor_height = 0,
|
||||
.icon_height = 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -449,6 +449,7 @@ pub const DerivedConfig = struct {
|
||||
@"adjust-cursor-thickness": ?Metrics.Modifier,
|
||||
@"adjust-cursor-height": ?Metrics.Modifier,
|
||||
@"adjust-box-thickness": ?Metrics.Modifier,
|
||||
@"adjust-icon-height": ?Metrics.Modifier,
|
||||
@"freetype-load-flags": font.face.FreetypeLoadFlags,
|
||||
|
||||
/// Initialize a DerivedConfig. The config should be either a
|
||||
@ -488,6 +489,7 @@ pub const DerivedConfig = struct {
|
||||
.@"adjust-cursor-thickness" = config.@"adjust-cursor-thickness",
|
||||
.@"adjust-cursor-height" = config.@"adjust-cursor-height",
|
||||
.@"adjust-box-thickness" = config.@"adjust-box-thickness",
|
||||
.@"adjust-icon-height" = config.@"adjust-icon-height",
|
||||
.@"freetype-load-flags" = if (font.face.FreetypeLoadFlags != void) config.@"freetype-load-flags" else {},
|
||||
|
||||
// This must be last so the arena contains all our allocations
|
||||
@ -634,6 +636,7 @@ pub const Key = struct {
|
||||
if (config.@"adjust-cursor-thickness") |m| try set.put(alloc, .cursor_thickness, m);
|
||||
if (config.@"adjust-cursor-height") |m| try set.put(alloc, .cursor_height, m);
|
||||
if (config.@"adjust-box-thickness") |m| try set.put(alloc, .box_thickness, m);
|
||||
if (config.@"adjust-icon-height") |m| try set.put(alloc, .icon_height, m);
|
||||
break :set set;
|
||||
};
|
||||
|
||||
|
@ -144,12 +144,32 @@ pub const RenderOptions = struct {
|
||||
/// Bottom padding when resizing.
|
||||
pad_bottom: f64 = 0.0,
|
||||
|
||||
// This acts as a multiple of the provided width when applying
|
||||
// constraints, so if this is 1.6 for example, then a width of
|
||||
// 10 would be treated as though it were 16.
|
||||
group_width: f64 = 1.0,
|
||||
// This acts as a multiple of the provided height when applying
|
||||
// constraints, so if this is 1.6 for example, then a height of
|
||||
// 10 would be treated as though it were 16.
|
||||
group_height: f64 = 1.0,
|
||||
// This is an x offset for the actual width within the group width.
|
||||
// If this is 0.5 then the glyph will be offset so that its left
|
||||
// edge sits at the halfway point of the group width.
|
||||
group_x: f64 = 0.0,
|
||||
// This is a y offset for the actual height within the group height.
|
||||
// If this is 0.5 then the glyph will be offset so that its bottom
|
||||
// edge sits at the halfway point of the group height.
|
||||
group_y: f64 = 0.0,
|
||||
|
||||
/// Maximum ratio of width to height when resizing.
|
||||
max_xy_ratio: ?f64 = null,
|
||||
|
||||
/// Maximum number of cells horizontally to use.
|
||||
max_constraint_width: u2 = 2,
|
||||
|
||||
/// What to use as the height metric when constraining the glyph.
|
||||
height: Height = .cell,
|
||||
|
||||
pub const Size = enum {
|
||||
/// Don't change the size of this glyph.
|
||||
none,
|
||||
@ -176,6 +196,13 @@ pub const RenderOptions = struct {
|
||||
center,
|
||||
};
|
||||
|
||||
pub const Height = enum {
|
||||
/// Use the full height of the cell for constraining this glyph.
|
||||
cell,
|
||||
/// Use the "icon height" from the grid metrics as the height.
|
||||
icon,
|
||||
};
|
||||
|
||||
/// The size and position of a glyph.
|
||||
pub const GlyphSize = struct {
|
||||
width: f64,
|
||||
@ -189,35 +216,55 @@ pub const RenderOptions = struct {
|
||||
pub fn constrain(
|
||||
self: Constraint,
|
||||
glyph: GlyphSize,
|
||||
/// Width of one cell.
|
||||
cell_width: f64,
|
||||
/// Height of one cell.
|
||||
cell_height: f64,
|
||||
metrics: Metrics,
|
||||
/// Number of cells horizontally available for this glyph.
|
||||
constraint_width: u2,
|
||||
) GlyphSize {
|
||||
var g = glyph;
|
||||
|
||||
const available_width =
|
||||
cell_width * @as(f64, @floatFromInt(
|
||||
@min(
|
||||
self.max_constraint_width,
|
||||
constraint_width,
|
||||
),
|
||||
));
|
||||
var available_width: f64 = @floatFromInt(
|
||||
metrics.cell_width * @min(
|
||||
self.max_constraint_width,
|
||||
constraint_width,
|
||||
),
|
||||
);
|
||||
const available_height: f64 = @floatFromInt(switch (self.height) {
|
||||
.cell => metrics.cell_height,
|
||||
.icon => metrics.icon_height,
|
||||
});
|
||||
|
||||
// We make the opinionated choice here to reduce the width
|
||||
// of icon-height symbols by the same amount horizontally,
|
||||
// since otherwise wide aspect ratio icons like folders end
|
||||
// up far too wide.
|
||||
//
|
||||
// But we *only* do this if the constraint width is 2, since
|
||||
// otherwise it would make them way too small when sized for
|
||||
// a single cell.
|
||||
const is_icon_width = self.height == .icon and @min(self.max_constraint_width, constraint_width) > 1;
|
||||
const orig_avail_width = available_width;
|
||||
if (is_icon_width) {
|
||||
const cell_height: f64 = @floatFromInt(metrics.cell_height);
|
||||
const ratio = available_height / cell_height;
|
||||
available_width *= ratio;
|
||||
}
|
||||
|
||||
const w = available_width -
|
||||
self.pad_left * available_width -
|
||||
self.pad_right * available_width;
|
||||
const h = cell_height -
|
||||
self.pad_top * cell_height -
|
||||
self.pad_bottom * cell_height;
|
||||
const h = available_height -
|
||||
self.pad_top * available_height -
|
||||
self.pad_bottom * available_height;
|
||||
|
||||
// Subtract padding from the bearings so that our
|
||||
// alignment and sizing code works correctly. We
|
||||
// re-add before returning.
|
||||
g.x -= self.pad_left * available_width;
|
||||
g.y -= self.pad_bottom * cell_height;
|
||||
g.y -= self.pad_bottom * available_height;
|
||||
|
||||
// Multiply by group width and height for better sizing.
|
||||
g.width *= self.group_width;
|
||||
g.height *= self.group_height;
|
||||
|
||||
switch (self.size_horizontal) {
|
||||
.none => {},
|
||||
@ -297,6 +344,14 @@ pub const RenderOptions = struct {
|
||||
},
|
||||
}
|
||||
|
||||
// Add group-relative position
|
||||
g.x += self.group_x * g.width;
|
||||
g.y += self.group_y * g.height;
|
||||
|
||||
// Divide group width and height back out before we align.
|
||||
g.width /= self.group_width;
|
||||
g.height /= self.group_height;
|
||||
|
||||
if (self.max_xy_ratio) |ratio| if (g.width > g.height * ratio) {
|
||||
const orig_width = g.width;
|
||||
g.width = g.height * ratio;
|
||||
@ -317,9 +372,23 @@ pub const RenderOptions = struct {
|
||||
.center => g.y = (h - g.height) / 2,
|
||||
}
|
||||
|
||||
// Add offset for icon width restriction, to keep it centered.
|
||||
if (is_icon_width) {
|
||||
g.x += (orig_avail_width - available_width) / 2;
|
||||
}
|
||||
|
||||
// Re-add our padding before returning.
|
||||
g.x += self.pad_left * available_width;
|
||||
g.y += self.pad_bottom * cell_height;
|
||||
g.y += self.pad_bottom * available_height;
|
||||
|
||||
// If the available height is less than the cell height, we
|
||||
// add half of the difference to center it in the full height.
|
||||
//
|
||||
// If necessary, in the future, we can adjust this to account
|
||||
// for alignment, but that isn't necessary with any of the nf
|
||||
// icons afaict.
|
||||
const cell_height: f64 = @floatFromInt(metrics.cell_height);
|
||||
g.y += (cell_height - available_height) / 2;
|
||||
|
||||
return g;
|
||||
}
|
||||
|
@ -31,6 +31,9 @@ pub const Face = struct {
|
||||
/// tables).
|
||||
color: ?ColorState = null,
|
||||
|
||||
/// The current size this font is set to.
|
||||
size: font.face.DesiredSize,
|
||||
|
||||
/// True if our build is using Harfbuzz. If we're not, we can avoid
|
||||
/// some Harfbuzz-specific code paths.
|
||||
const harfbuzz_shaper = font.options.backend.hasHarfbuzz();
|
||||
@ -106,6 +109,7 @@ pub const Face = struct {
|
||||
.font = ct_font,
|
||||
.hb_font = hb_font,
|
||||
.color = color,
|
||||
.size = opts.size,
|
||||
};
|
||||
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
||||
|
||||
@ -333,38 +337,99 @@ pub const Face = struct {
|
||||
.offset_y = 0,
|
||||
.atlas_x = 0,
|
||||
.atlas_y = 0,
|
||||
.advance_x = 0,
|
||||
};
|
||||
|
||||
const metrics = opts.grid_metrics;
|
||||
const cell_width: f64 = @floatFromInt(metrics.cell_width);
|
||||
const cell_height: f64 = @floatFromInt(metrics.cell_height);
|
||||
// const cell_height: f64 = @floatFromInt(metrics.cell_height);
|
||||
|
||||
const glyph_size = opts.constraint.constrain(
|
||||
// We eliminate any negative vertical padding since these overlap
|
||||
// values aren't needed under CoreText with how precisely we apply
|
||||
// constraints, and they can lead to extra height that looks bad
|
||||
// for things like powerline glyphs.
|
||||
var constraint = opts.constraint;
|
||||
constraint.pad_top = @max(0.0, constraint.pad_top);
|
||||
constraint.pad_bottom = @max(0.0, constraint.pad_bottom);
|
||||
const glyph_size = constraint.constrain(
|
||||
.{
|
||||
.width = rect.size.width,
|
||||
.height = rect.size.height,
|
||||
.x = rect.origin.x,
|
||||
.y = rect.origin.y + @as(f64, @floatFromInt(metrics.cell_baseline)),
|
||||
},
|
||||
cell_width,
|
||||
cell_height,
|
||||
metrics,
|
||||
opts.constraint_width,
|
||||
);
|
||||
|
||||
const width = glyph_size.width;
|
||||
const height = glyph_size.height;
|
||||
const x = glyph_size.x;
|
||||
const y = glyph_size.y;
|
||||
// These calculations are an attempt to mostly imitate the effect of
|
||||
// `shouldSubpixelQuantizeFonts`[^1], which helps maximize legibility
|
||||
// at small pixel sizes (low DPI). We do this math ourselves instead
|
||||
// of letting CoreText do it because it's not entirely clear how the
|
||||
// math in CoreText works and we've run in to edge cases where glyphs
|
||||
// have their bottom or left row cut off due to bad rounding.
|
||||
//
|
||||
// This math seems to have a mostly comparable result to whatever it
|
||||
// is that CoreText does, and is even (in my opinion) better in some
|
||||
// cases.
|
||||
//
|
||||
// I'm not entirely certain but I suspect that when you enable the
|
||||
// CoreText option it also does some sort of rudimentary hinting,
|
||||
// but it doesn't seem to make that big of a difference in terms
|
||||
// of legibility in the end.
|
||||
//
|
||||
// [^1]: https://developer.apple.com/documentation/coregraphics/cgcontext/setshouldsubpixelquantizefonts(_:)?language=objc
|
||||
|
||||
// We have to include the fractional pixels that we won't be offsetting
|
||||
// in our width and height calculations, that is, we offset by the floor
|
||||
// of the bearings when we render the glyph, meaning there's still a bit
|
||||
// of extra width to the area that's drawn in beyond just the width of
|
||||
// the glyph itself, so we include that extra fraction of a pixel when
|
||||
// calculating the width and height here.
|
||||
const px_width: u32 = @intFromFloat(@ceil(width + rect.origin.x - @floor(rect.origin.x)));
|
||||
const px_height: u32 = @intFromFloat(@ceil(height + rect.origin.y - @floor(rect.origin.y)));
|
||||
// We only want to apply quantization if we don't have any
|
||||
// constraints and this isn't a bitmap glyph, since CoreText
|
||||
// doesn't seem to apply its quantization to bitmap glyphs.
|
||||
//
|
||||
// TODO: Maybe gate this so it only applies at small font sizes,
|
||||
// or else offer a user config option that can disable it.
|
||||
const should_quantize = !sbix and std.meta.eql(opts.constraint, .none);
|
||||
|
||||
// We offset our glyph by its bearings when we draw it, using `@floor`
|
||||
// here rounds it *up* since we negate it right outside. Moving it by
|
||||
// whole pixels ensures that we don't disturb the pixel alignment of
|
||||
// the glyph, fractional pixels will still be drawn on all sides as
|
||||
// necessary.
|
||||
const draw_x = -@floor(rect.origin.x);
|
||||
const draw_y = -@floor(rect.origin.y);
|
||||
|
||||
// We use `x` and `y` for our full pixel bearings post-raster.
|
||||
// We need to subtract the fractional pixel of difference from
|
||||
// the edge of the draw area to the edge of the actual glyph.
|
||||
const frac_x = rect.origin.x + draw_x;
|
||||
const frac_y = rect.origin.y + draw_y;
|
||||
const x = glyph_size.x - frac_x;
|
||||
const y = glyph_size.y - frac_y;
|
||||
|
||||
// We never modify the width.
|
||||
//
|
||||
// When using the CoreText option the widths do seem to be
|
||||
// modified extremely subtly, but even at very small font
|
||||
// sizes it's hardly a noticeable difference.
|
||||
const width = glyph_size.width;
|
||||
|
||||
// If the top of the glyph (taking in to account the y position)
|
||||
// is within half a pixel of an exact pixel edge, we round up the
|
||||
// height, otherwise leave it alone.
|
||||
//
|
||||
// This seems to match what CoreText does.
|
||||
const frac_top = (glyph_size.height + frac_y) - @floor(glyph_size.height + frac_y);
|
||||
const height =
|
||||
if (should_quantize)
|
||||
if (frac_top >= 0.5)
|
||||
glyph_size.height + 1 - frac_top
|
||||
else
|
||||
glyph_size.height
|
||||
else
|
||||
glyph_size.height;
|
||||
|
||||
// Add the fractional pixel to the width and height and take
|
||||
// the ceiling to get a canvas size that will definitely fit
|
||||
// our drawn glyph.
|
||||
const px_width: u32 = @intFromFloat(@ceil(width + frac_x));
|
||||
const px_height: u32 = @intFromFloat(@ceil(height + frac_y));
|
||||
|
||||
// Settings that are specific to if we are rendering text or emoji.
|
||||
const color: struct {
|
||||
@ -429,12 +494,23 @@ pub const Face = struct {
|
||||
},
|
||||
});
|
||||
|
||||
// "Font smoothing" is what we call "thickening", it's an attempt
|
||||
// to compensate for optical thinning of fonts, but at this point
|
||||
// it's just something that makes the text look closer to system
|
||||
// applications if users want that.
|
||||
context.setAllowsFontSmoothing(ctx, true);
|
||||
context.setShouldSmoothFonts(ctx, opts.thicken); // The amadeus "enthicken"
|
||||
context.setAllowsFontSubpixelQuantization(ctx, true);
|
||||
context.setShouldSubpixelQuantizeFonts(ctx, true);
|
||||
context.setShouldSmoothFonts(ctx, opts.thicken);
|
||||
|
||||
// Subpixel positioning allows glyphs to be placed at non-integer
|
||||
// coordinates. We need this for our alignment.
|
||||
context.setAllowsFontSubpixelPositioning(ctx, true);
|
||||
context.setShouldSubpixelPositionFonts(ctx, true);
|
||||
|
||||
// See comments about quantization earlier in the function.
|
||||
context.setAllowsFontSubpixelQuantization(ctx, false);
|
||||
context.setShouldSubpixelQuantizeFonts(ctx, false);
|
||||
|
||||
// Anti-aliasing is self explanatory.
|
||||
context.setAllowsAntialiasing(ctx, true);
|
||||
context.setShouldAntialias(ctx, true);
|
||||
|
||||
@ -455,19 +531,16 @@ pub const Face = struct {
|
||||
context.setLineWidth(ctx, line_width);
|
||||
}
|
||||
|
||||
// Scale the drawing context so that when we draw
|
||||
// our glyph it's stretched to the constrained size.
|
||||
context.scaleCTM(
|
||||
ctx,
|
||||
width / rect.size.width,
|
||||
height / rect.size.height,
|
||||
);
|
||||
|
||||
// We want to render the glyphs at (0,0), but the glyphs themselves
|
||||
// are offset by bearings, so we have to undo those bearings in order
|
||||
// to get them to 0,0.
|
||||
self.font.drawGlyphs(&glyphs, &.{.{
|
||||
.x = -@floor(rect.origin.x),
|
||||
.y = -@floor(rect.origin.y),
|
||||
}}, ctx);
|
||||
// Draw our glyph.
|
||||
self.font.drawGlyphs(&glyphs, &.{.{ .x = draw_x, .y = draw_y }}, ctx);
|
||||
|
||||
// Write our rasterized glyph to the atlas.
|
||||
const region = try atlas.reserve(alloc, px_width, px_height);
|
||||
@ -475,33 +548,47 @@ pub const Face = struct {
|
||||
|
||||
// This should be the distance from the bottom of
|
||||
// the cell to the top of the glyph's bounding box.
|
||||
const offset_y: i32 =
|
||||
@as(i32, @intFromFloat(@floor(y))) +
|
||||
@as(i32, @intCast(px_height));
|
||||
const offset_y: i32 = @as(i32, @intFromFloat(@round(y))) + @as(i32, @intCast(px_height));
|
||||
|
||||
// This should be the distance from the left of
|
||||
// the cell to the left of the glyph's bounding box.
|
||||
const offset_x: i32 = offset_x: {
|
||||
var result: i32 = @intFromFloat(@round(x));
|
||||
|
||||
// If our cell was resized then we adjust our glyph's
|
||||
// position relative to the new center. This keeps glyphs
|
||||
// centered in the cell whether it was made wider or narrower.
|
||||
if (metrics.original_cell_width) |original_width| {
|
||||
const before: i32 = @intCast(original_width);
|
||||
const after: i32 = @intCast(metrics.cell_width);
|
||||
// Increase the offset by half of the difference
|
||||
// between the widths to keep things centered.
|
||||
result += @divTrunc(after - before, 2);
|
||||
// If the glyph's advance is narrower than the cell width then we
|
||||
// center the advance of the glyph within the cell width. At first
|
||||
// I implemented this to proportionally scale the center position
|
||||
// of the glyph but that messes up glyphs that are meant to align
|
||||
// vertically with others, so this is a compromise.
|
||||
//
|
||||
// This makes it so that when the `adjust-cell-width` config is
|
||||
// used, or when a fallback font with a different advance width
|
||||
// is used, we don't get weirdly aligned glyphs.
|
||||
//
|
||||
// We don't do this if the constraint has a horizontal alignment,
|
||||
// since in that case the position was already calculated with the
|
||||
// new cell width in mind.
|
||||
if (opts.constraint.align_horizontal == .none) {
|
||||
const advance = self.font.getAdvancesForGlyphs(.horizontal, &glyphs, null);
|
||||
const new_advance =
|
||||
cell_width * @as(f64, @floatFromInt(opts.cell_width orelse 1));
|
||||
// If the original advance is greater than the cell width then
|
||||
// it's possible that this is a ligature or other glyph that is
|
||||
// intended to overflow the cell to one side or the other, and
|
||||
// adjusting the bearings could mess that up, so we just leave
|
||||
// it alone if that's the case.
|
||||
//
|
||||
// We also don't want to do anything if the advance is zero or
|
||||
// less, since this is used for stuff like combining characters.
|
||||
if (advance > new_advance or advance <= 0.0) {
|
||||
break :offset_x @intFromFloat(@round(x));
|
||||
}
|
||||
break :offset_x @intFromFloat(
|
||||
@round(x + (new_advance - advance) / 2),
|
||||
);
|
||||
} else {
|
||||
break :offset_x @intFromFloat(@round(x));
|
||||
}
|
||||
|
||||
break :offset_x result;
|
||||
};
|
||||
|
||||
// Get our advance
|
||||
var advances: [glyphs.len]macos.graphics.Size = undefined;
|
||||
_ = self.font.getAdvancesForGlyphs(.horizontal, &glyphs, &advances);
|
||||
|
||||
return .{
|
||||
.width = px_width,
|
||||
.height = px_height,
|
||||
@ -509,7 +596,6 @@ pub const Face = struct {
|
||||
.offset_y = offset_y,
|
||||
.atlas_x = region.x,
|
||||
.atlas_y = region.y,
|
||||
.advance_x = @floatCast(advances[0].width),
|
||||
};
|
||||
}
|
||||
|
||||
@ -741,6 +827,20 @@ pub const Face = struct {
|
||||
break :cell_width max;
|
||||
};
|
||||
|
||||
// Measure "水" (CJK water ideograph, U+6C34) for our ic width.
|
||||
const ic_width: ?f64 = ic_width: {
|
||||
const glyph = self.glyphIndex('水') orelse break :ic_width null;
|
||||
|
||||
var advances: [1]macos.graphics.Size = undefined;
|
||||
_ = ct_font.getAdvancesForGlyphs(
|
||||
.horizontal,
|
||||
&.{@intCast(glyph)},
|
||||
&advances,
|
||||
);
|
||||
|
||||
break :ic_width advances[0].width;
|
||||
};
|
||||
|
||||
return .{
|
||||
.cell_width = cell_width,
|
||||
.ascent = ascent,
|
||||
@ -752,6 +852,7 @@ pub const Face = struct {
|
||||
.strikethrough_thickness = strikethrough_thickness,
|
||||
.cap_height = cap_height,
|
||||
.ex_height = ex_height,
|
||||
.ic_width = ic_width,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,9 @@ pub const Face = struct {
|
||||
bold: bool = false,
|
||||
} = .{},
|
||||
|
||||
/// The current size this font is set to.
|
||||
size: font.face.DesiredSize,
|
||||
|
||||
/// Initialize a new font face with the given source in-memory.
|
||||
pub fn initFile(
|
||||
lib: Library,
|
||||
@ -107,6 +110,7 @@ pub const Face = struct {
|
||||
.hb_font = hb_font,
|
||||
.ft_mutex = ft_mutex,
|
||||
.load_flags = opts.freetype_load_flags,
|
||||
.size = opts.size,
|
||||
};
|
||||
result.quirks_disable_default_font_features = quirks.disableDefaultFontFeatures(&result);
|
||||
|
||||
@ -203,6 +207,7 @@ pub const Face = struct {
|
||||
/// for clearing any glyph caches, font atlas data, etc.
|
||||
pub fn setSize(self: *Face, opts: font.face.Options) !void {
|
||||
try setSize_(self.face, opts.size);
|
||||
self.size = opts.size;
|
||||
}
|
||||
|
||||
fn setSize_(face: freetype.Face, size: font.face.DesiredSize) !void {
|
||||
@ -373,7 +378,6 @@ pub const Face = struct {
|
||||
.offset_y = 0,
|
||||
.atlas_x = 0,
|
||||
.atlas_y = 0,
|
||||
.advance_x = 0,
|
||||
};
|
||||
|
||||
// For synthetic bold, we embolden the glyph.
|
||||
@ -391,7 +395,7 @@ pub const Face = struct {
|
||||
const metrics = opts.grid_metrics;
|
||||
|
||||
const cell_width: f64 = @floatFromInt(metrics.cell_width);
|
||||
const cell_height: f64 = @floatFromInt(metrics.cell_height);
|
||||
// const cell_height: f64 = @floatFromInt(metrics.cell_height);
|
||||
|
||||
const glyph_x: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingX);
|
||||
const glyph_y: f64 = f26dot6ToF64(glyph.*.metrics.horiBearingY) - glyph_height;
|
||||
@ -403,8 +407,7 @@ pub const Face = struct {
|
||||
.x = glyph_x,
|
||||
.y = glyph_y + @as(f64, @floatFromInt(metrics.cell_baseline)),
|
||||
},
|
||||
cell_width,
|
||||
cell_height,
|
||||
metrics,
|
||||
opts.constraint_width,
|
||||
);
|
||||
|
||||
@ -639,20 +642,40 @@ pub const Face = struct {
|
||||
// This should be the distance from the left of
|
||||
// the cell to the left of the glyph's bounding box.
|
||||
const offset_x: i32 = offset_x: {
|
||||
var result: i32 = @intFromFloat(@floor(x));
|
||||
|
||||
// If our cell was resized then we adjust our glyph's
|
||||
// position relative to the new center. This keeps glyphs
|
||||
// centered in the cell whether it was made wider or narrower.
|
||||
if (metrics.original_cell_width) |original_width| {
|
||||
const before: i32 = @intCast(original_width);
|
||||
const after: i32 = @intCast(metrics.cell_width);
|
||||
// Increase the offset by half of the difference
|
||||
// between the widths to keep things centered.
|
||||
result += @divTrunc(after - before, 2);
|
||||
// If the glyph's advance is narrower than the cell width then we
|
||||
// center the advance of the glyph within the cell width. At first
|
||||
// I implemented this to proportionally scale the center position
|
||||
// of the glyph but that messes up glyphs that are meant to align
|
||||
// vertically with others, so this is a compromise.
|
||||
//
|
||||
// This makes it so that when the `adjust-cell-width` config is
|
||||
// used, or when a fallback font with a different advance width
|
||||
// is used, we don't get weirdly aligned glyphs.
|
||||
//
|
||||
// We don't do this if the constraint has a horizontal alignment,
|
||||
// since in that case the position was already calculated with the
|
||||
// new cell width in mind.
|
||||
if (opts.constraint.align_horizontal == .none) {
|
||||
const advance = f26dot6ToFloat(glyph.*.advance.x);
|
||||
const new_advance =
|
||||
cell_width * @as(f64, @floatFromInt(opts.cell_width orelse 1));
|
||||
// If the original advance is greater than the cell width then
|
||||
// it's possible that this is a ligature or other glyph that is
|
||||
// intended to overflow the cell to one side or the other, and
|
||||
// adjusting the bearings could mess that up, so we just leave
|
||||
// it alone if that's the case.
|
||||
//
|
||||
// We also don't want to do anything if the advance is zero or
|
||||
// less, since this is used for stuff like combining characters.
|
||||
if (advance > new_advance or advance <= 0.0) {
|
||||
break :offset_x @intFromFloat(@floor(x));
|
||||
}
|
||||
break :offset_x @intFromFloat(
|
||||
@floor(x + (new_advance - advance) / 2),
|
||||
);
|
||||
} else {
|
||||
break :offset_x @intFromFloat(@floor(x));
|
||||
}
|
||||
|
||||
break :offset_x result;
|
||||
};
|
||||
|
||||
return Glyph{
|
||||
@ -662,7 +685,6 @@ pub const Face = struct {
|
||||
.offset_y = offset_y,
|
||||
.atlas_x = region.x,
|
||||
.atlas_y = region.y,
|
||||
.advance_x = f26dot6ToFloat(glyph.*.advance.x),
|
||||
};
|
||||
}
|
||||
|
||||
@ -833,7 +855,7 @@ pub const Face = struct {
|
||||
while (c < 127) : (c += 1) {
|
||||
if (face.getCharIndex(c)) |glyph_index| {
|
||||
if (face.loadGlyph(glyph_index, .{
|
||||
.render = true,
|
||||
.render = false,
|
||||
.no_svg = true,
|
||||
})) {
|
||||
max = @max(
|
||||
@ -871,7 +893,7 @@ pub const Face = struct {
|
||||
defer self.ft_mutex.unlock();
|
||||
if (face.getCharIndex('H')) |glyph_index| {
|
||||
if (face.loadGlyph(glyph_index, .{
|
||||
.render = true,
|
||||
.render = false,
|
||||
.no_svg = true,
|
||||
})) {
|
||||
break :cap f26dot6ToF64(face.handle.*.glyph.*.metrics.height);
|
||||
@ -884,7 +906,7 @@ pub const Face = struct {
|
||||
defer self.ft_mutex.unlock();
|
||||
if (face.getCharIndex('x')) |glyph_index| {
|
||||
if (face.loadGlyph(glyph_index, .{
|
||||
.render = true,
|
||||
.render = false,
|
||||
.no_svg = true,
|
||||
})) {
|
||||
break :ex f26dot6ToF64(face.handle.*.glyph.*.metrics.height);
|
||||
@ -895,6 +917,21 @@ pub const Face = struct {
|
||||
};
|
||||
};
|
||||
|
||||
// Measure "水" (CJK water ideograph, U+6C34) for our ic width.
|
||||
const ic_width: ?f64 = ic_width: {
|
||||
self.ft_mutex.lock();
|
||||
defer self.ft_mutex.unlock();
|
||||
|
||||
const glyph = face.getCharIndex('水') orelse break :ic_width null;
|
||||
|
||||
face.loadGlyph(glyph, .{
|
||||
.render = false,
|
||||
.no_svg = true,
|
||||
}) catch break :ic_width null;
|
||||
|
||||
break :ic_width f26dot6ToF64(face.handle.*.glyph.*.advance.x);
|
||||
};
|
||||
|
||||
return .{
|
||||
.cell_width = cell_width,
|
||||
|
||||
@ -910,6 +947,7 @@ pub const Face = struct {
|
||||
|
||||
.cap_height = cap_height,
|
||||
.ex_height = ex_height,
|
||||
.ic_width = ic_width,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1019,6 +1057,7 @@ test "color emoji" {
|
||||
.overline_thickness = 0,
|
||||
.box_thickness = 0,
|
||||
.cursor_height = 0,
|
||||
.icon_height = 0,
|
||||
}, .constraint_width = 2, .constraint = .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .cover,
|
||||
|
@ -235,7 +235,6 @@ pub const Face = struct {
|
||||
.offset_y = 0,
|
||||
.atlas_x = region.x,
|
||||
.atlas_y = region.y,
|
||||
.advance_x = 0,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.max_constraint_width = 1,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
@ -33,7 +34,35 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
.pad_top = 0.1,
|
||||
.pad_bottom = 0.1,
|
||||
},
|
||||
0x276c...0x2771,
|
||||
0x276c...0x276d,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
.max_constraint_width = 1,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.4028056112224450,
|
||||
.group_height = 1.1222570532915361,
|
||||
.group_x = 0.1428571428571428,
|
||||
.group_y = 0.0349162011173184,
|
||||
.pad_top = 0.15,
|
||||
.pad_bottom = 0.15,
|
||||
},
|
||||
0x276e...0x276f,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
.max_constraint_width = 1,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0115606936416186,
|
||||
.group_height = 1.1222570532915361,
|
||||
.group_x = 0.0057142857142857,
|
||||
.group_y = 0.0125698324022346,
|
||||
.pad_top = 0.15,
|
||||
.pad_bottom = 0.15,
|
||||
},
|
||||
0x2770...0x2771,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .fit,
|
||||
@ -285,7 +314,7 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
0xe0d0...0xe0d1,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .cover,
|
||||
.size_vertical = .fit,
|
||||
.align_horizontal = .start,
|
||||
.align_vertical = .center,
|
||||
},
|
||||
@ -294,7 +323,7 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
0xe0d5,
|
||||
=> .{
|
||||
.size_horizontal = .cover,
|
||||
.size_vertical = .cover,
|
||||
.size_vertical = .fit,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
},
|
||||
@ -356,15 +385,689 @@ pub fn getConstraint(cp: u21) Constraint {
|
||||
0x2b58,
|
||||
0xe000...0xe0a9,
|
||||
0xe4fa...0xe7ef,
|
||||
0xea60...0xec1e,
|
||||
0xed00...0xf847,
|
||||
0xea60,
|
||||
0xea62...0xea7c,
|
||||
0xea7e...0xea98,
|
||||
0xeaa3...0xeab3,
|
||||
0xeab8...0xead3,
|
||||
0xead7...0xeb42,
|
||||
0xeb44...0xeb6d,
|
||||
0xeb72...0xeb89,
|
||||
0xeb8b...0xeb99,
|
||||
0xeb9b...0xebd4,
|
||||
0xebd6,
|
||||
0xebd8...0xec06,
|
||||
0xec08...0xec0a,
|
||||
0xec0d...0xec1e,
|
||||
0xed00...0xf018,
|
||||
0xf01a...0xf02f,
|
||||
0xf031...0xf03c,
|
||||
0xf041...0xf043,
|
||||
0xf045...0xf049,
|
||||
0xf04b...0xf050,
|
||||
0xf054...0xf059,
|
||||
0xf05c...0xf070,
|
||||
0xf072...0xf077,
|
||||
0xf079...0xf07a,
|
||||
0xf07c...0xf080,
|
||||
0xf082...0xf08b,
|
||||
0xf08d...0xf091,
|
||||
0xf093...0xf09b,
|
||||
0xf09d...0xf09e,
|
||||
0xf0a0,
|
||||
0xf0a5...0xf0a9,
|
||||
0xf0ab...0xf0c9,
|
||||
0xf0cb...0xf0d5,
|
||||
0xf0d7...0xf0dd,
|
||||
0xf0df...0xf0e6,
|
||||
0xf0e8...0xf295,
|
||||
0xf297...0xf2c1,
|
||||
0xf2c6...0xf2ef,
|
||||
0xf2f1...0xf305,
|
||||
0xf307...0xf847,
|
||||
0xf0001...0xf1af0,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
},
|
||||
0xea61,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3315669947009841,
|
||||
.group_height = 1.0763840224246670,
|
||||
.group_x = 0.0847072200113701,
|
||||
.group_y = 0.0709635416666667,
|
||||
},
|
||||
0xea7d,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1913145539906103,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_x = 0.0916256157635468,
|
||||
.group_y = 0.0415039062500000,
|
||||
},
|
||||
0xea99,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0639412997903563,
|
||||
.group_height = 2.0940695296523519,
|
||||
.group_x = 0.0295566502463054,
|
||||
.group_y = 0.2270507812500000,
|
||||
},
|
||||
0xea9a,
|
||||
0xeaa1,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3029525032092426,
|
||||
.group_height = 1.1729667812142039,
|
||||
.group_x = 0.1527093596059113,
|
||||
.group_y = 0.0751953125000000,
|
||||
},
|
||||
0xea9b,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1639908256880733,
|
||||
.group_height = 1.3128205128205128,
|
||||
.group_x = 0.0719211822660099,
|
||||
.group_y = 0.0869140625000000,
|
||||
},
|
||||
0xea9c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1639908256880733,
|
||||
.group_height = 1.3195876288659794,
|
||||
.group_x = 0.0719211822660099,
|
||||
.group_y = 0.0830078125000000,
|
||||
},
|
||||
0xea9d,
|
||||
0xeaa0,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.4457831325301207,
|
||||
.group_height = 1.9692307692307693,
|
||||
.group_x = 0.2857142857142857,
|
||||
.group_y = 0.2763671875000000,
|
||||
},
|
||||
0xea9e...0xea9f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.9556840077071291,
|
||||
.group_height = 2.4674698795180725,
|
||||
.group_x = 0.2137931034482759,
|
||||
.group_y = 0.3066406250000000,
|
||||
},
|
||||
0xeaa2,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2412121212121212,
|
||||
.group_height = 1.0591799039527152,
|
||||
.group_x = 0.0683593750000000,
|
||||
.group_y = 0.0146484375000000,
|
||||
},
|
||||
0xeab4,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0049115913555993,
|
||||
.group_height = 1.8998144712430427,
|
||||
.group_y = 0.2026367187500000,
|
||||
},
|
||||
0xeab5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.8979591836734695,
|
||||
.group_height = 1.0054000981836033,
|
||||
.group_x = 0.2023460410557185,
|
||||
.group_y = 0.0053710937500000,
|
||||
},
|
||||
0xeab6,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.8979591836734695,
|
||||
.group_height = 1.0054000981836033,
|
||||
.group_x = 0.2707722385141740,
|
||||
},
|
||||
0xeab7,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0049115913555993,
|
||||
.group_height = 1.8980537534754403,
|
||||
.group_x = 0.0048875855327468,
|
||||
.group_y = 0.2709960937500000,
|
||||
},
|
||||
0xead4...0xead5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.4152542372881356,
|
||||
.group_x = 0.1486118671747414,
|
||||
},
|
||||
0xead6,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.1390433815350389,
|
||||
.group_y = 0.0688476562500000,
|
||||
},
|
||||
0xeb43,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3635153129161119,
|
||||
.group_height = 1.0002360944082516,
|
||||
.group_x = 0.1992187500000000,
|
||||
.group_y = 0.0002360386808388,
|
||||
},
|
||||
0xeb6e,
|
||||
0xeb71,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 2.0197238658777121,
|
||||
.group_y = 0.2524414062500000,
|
||||
},
|
||||
0xeb6f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.0098619329388558,
|
||||
.group_x = 0.2492639842983317,
|
||||
},
|
||||
0xeb70,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.0098619329388558,
|
||||
.group_height = 1.0039215686274510,
|
||||
.group_x = 0.2492639842983317,
|
||||
.group_y = 0.0039062500000000,
|
||||
},
|
||||
0xeb8a,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.8826979472140764,
|
||||
.group_height = 2.9804097167804766,
|
||||
.group_x = 0.2634791454730417,
|
||||
.group_y = 0.3314678485576923,
|
||||
},
|
||||
0xeb9a,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1441340782122904,
|
||||
.group_height = 1.0591799039527152,
|
||||
.group_x = 0.0683593750000000,
|
||||
.group_y = 0.0146484375000000,
|
||||
},
|
||||
0xebd5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0723270440251573,
|
||||
.group_height = 1.0728129910948141,
|
||||
.group_y = 0.0678710937500000,
|
||||
},
|
||||
0xebd7,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.0000418544302916,
|
||||
.group_y = 0.0000418526785714,
|
||||
},
|
||||
0xec07,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 2.8615369874243446,
|
||||
.group_height = 2.9789458113505249,
|
||||
.group_x = 0.2609446802539727,
|
||||
.group_y = 0.3313029661016949,
|
||||
},
|
||||
0xec0b,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0722513089005237,
|
||||
.group_height = 1.0002360944082516,
|
||||
.group_y = 0.0002360386808388,
|
||||
},
|
||||
0xec0c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2487804878048780,
|
||||
.group_x = 0.1992187500000000,
|
||||
},
|
||||
0xf019,
|
||||
0xf08c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
},
|
||||
0xf030,
|
||||
0xf03e,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_y = 0.0625000000000000,
|
||||
},
|
||||
0xf03d,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
.group_height = 1.5014662756598240,
|
||||
.group_y = 0.1669921875000000,
|
||||
},
|
||||
0xf03f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.6018762826150690,
|
||||
.group_x = 0.1876220107369448,
|
||||
},
|
||||
0xf040,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0006976906439684,
|
||||
.group_height = 1.0001808776182035,
|
||||
.group_x = 0.0006972042111134,
|
||||
.group_y = 0.0001808449074074,
|
||||
},
|
||||
0xf044,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1029147024980515,
|
||||
.group_height = 1.1024142703367676,
|
||||
.group_x = 0.0463592039005675,
|
||||
.group_y = 0.0430325010461710,
|
||||
},
|
||||
0xf04a,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004882812500000,
|
||||
.group_height = 1.3312975252838291,
|
||||
.group_y = 0.1245571402616279,
|
||||
},
|
||||
0xf051,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.6007812500000000,
|
||||
.group_height = 1.3312170271945341,
|
||||
.group_x = 0.1874084919472914,
|
||||
.group_y = 0.1245117187500000,
|
||||
},
|
||||
0xf052,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1436671384194865,
|
||||
.group_height = 1.1430165816326530,
|
||||
.group_x = 0.0624629273607646,
|
||||
.group_y = 0.0625610266424885,
|
||||
},
|
||||
0xf053,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.8765709864847797,
|
||||
.group_height = 1.0707191397207079,
|
||||
.group_x = 0.2332599943628554,
|
||||
.group_y = 0.0332682382480123,
|
||||
},
|
||||
0xf05a...0xf05b,
|
||||
0xf081,
|
||||
0xf092,
|
||||
0xf0aa,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.0001395089285714,
|
||||
.group_y = 0.0000697447342726,
|
||||
},
|
||||
0xf071,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0014662756598240,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_x = 0.0004880429477794,
|
||||
.group_y = 0.0625000000000000,
|
||||
},
|
||||
0xf078,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0717654378877508,
|
||||
.group_height = 1.8757195185766613,
|
||||
.group_x = 0.0331834301604062,
|
||||
.group_y = 0.1670386385827870,
|
||||
},
|
||||
0xf07b,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.1428571428571428,
|
||||
.group_y = 0.0625000000000000,
|
||||
},
|
||||
0xf09c,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.0810546875000000,
|
||||
},
|
||||
0xf09f,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.7506617925122907,
|
||||
.group_height = 1.0810546875000000,
|
||||
.group_x = 0.2143937211981567,
|
||||
},
|
||||
0xf0a1,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0009775171065494,
|
||||
.group_x = 0.0004882812500000,
|
||||
},
|
||||
0xf0a2,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.1433271023627367,
|
||||
.group_height = 1.0001395089285714,
|
||||
.group_x = 0.0624235731978609,
|
||||
.group_y = 0.0000697447342726,
|
||||
},
|
||||
0xf0a3,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005760656161586,
|
||||
.group_height = 1.0001220681837999,
|
||||
.group_x = 0.0004792774839344,
|
||||
.group_y = 0.0000610266424885,
|
||||
},
|
||||
0xf0a4,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.3335193452380951,
|
||||
.group_y = 0.1250523085507044,
|
||||
},
|
||||
0xf0ca,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.1922501247297521,
|
||||
.group_y = 0.0806249128190822,
|
||||
},
|
||||
0xf0d6,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_height = 1.5014662756598240,
|
||||
.group_y = 0.1669921875000000,
|
||||
},
|
||||
0xf0de,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2253421114919656,
|
||||
.group_height = 2.5216400911161729,
|
||||
.group_x = 0.0918898809523810,
|
||||
.group_y = 0.6034327009936766,
|
||||
},
|
||||
0xf0e7,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.3336843856081169,
|
||||
.group_x = 0.1247597299147187,
|
||||
},
|
||||
0xf296,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005148743038617,
|
||||
.group_height = 1.0385966606705219,
|
||||
.group_x = 0.0005146093447336,
|
||||
.group_y = 0.0186218440507742,
|
||||
},
|
||||
0xf2c2...0xf2c3,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0000770970394737,
|
||||
.group_height = 1.2864321608040201,
|
||||
.group_y = 0.1113281250000000,
|
||||
},
|
||||
0xf2c4,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0344231791600214,
|
||||
.group_x = 0.0166002826673519,
|
||||
},
|
||||
0xf2c5,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0004538836055876,
|
||||
.group_height = 1.4840579710144928,
|
||||
.group_x = 0.0004536776887225,
|
||||
.group_y = 0.1630859375000000,
|
||||
},
|
||||
0xf2f0,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.0005935142780173,
|
||||
.group_height = 1.0334438518091393,
|
||||
.group_y = 0.0161807783512345,
|
||||
},
|
||||
0xf306,
|
||||
=> .{
|
||||
.size_horizontal = .fit,
|
||||
.size_vertical = .fit,
|
||||
.height = .icon,
|
||||
.align_horizontal = .center,
|
||||
.align_vertical = .center,
|
||||
.group_width = 1.2427184466019416,
|
||||
.group_x = 0.0976562500000000,
|
||||
},
|
||||
else => .none,
|
||||
};
|
||||
}
|
||||
|
@ -7,11 +7,16 @@ attributes and scaling rules.
|
||||
This does include an `eval` call! This is spooky, but we trust the nerd fonts code to
|
||||
be safe and not malicious or anything.
|
||||
|
||||
This script requires Python 3.12 or greater.
|
||||
This script requires Python 3.12 or greater, requires that the `fontTools`
|
||||
python module is installed, and requires that the path to a copy of the
|
||||
SymbolsNerdFontMono font is passed as the first argument to the script.
|
||||
"""
|
||||
|
||||
import ast
|
||||
import sys
|
||||
import math
|
||||
from fontTools.ttLib import TTFont
|
||||
from fontTools.pens.boundsPen import BoundsPen
|
||||
from collections import defaultdict
|
||||
from contextlib import suppress
|
||||
from pathlib import Path
|
||||
@ -19,7 +24,18 @@ from types import SimpleNamespace
|
||||
from typing import Literal, TypedDict, cast
|
||||
|
||||
type PatchSetAttributes = dict[Literal["default"] | int, PatchSetAttributeEntry]
|
||||
type AttributeHash = tuple[str | None, str | None, str, float, float, float]
|
||||
type AttributeHash = tuple[
|
||||
str | None,
|
||||
str | None,
|
||||
str,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
float,
|
||||
]
|
||||
type ResolvedSymbol = PatchSetAttributes | PatchSetScaleRules | int | None
|
||||
|
||||
|
||||
@ -34,6 +50,11 @@ class PatchSetAttributeEntry(TypedDict):
|
||||
stretch: str
|
||||
params: dict[str, float | bool]
|
||||
|
||||
group_x: float
|
||||
group_y: float
|
||||
group_width: float
|
||||
group_height: float
|
||||
|
||||
|
||||
class PatchSet(TypedDict):
|
||||
SymStart: int
|
||||
@ -137,6 +158,10 @@ def attr_key(attr: PatchSetAttributeEntry) -> AttributeHash:
|
||||
float(params.get("overlap", 0.0)),
|
||||
float(params.get("xy-ratio", -1.0)),
|
||||
float(params.get("ypadding", 0.0)),
|
||||
float(attr.get("group_x", 0.0)),
|
||||
float(attr.get("group_y", 0.0)),
|
||||
float(attr.get("group_width", 1.0)),
|
||||
float(attr.get("group_height", 1.0)),
|
||||
)
|
||||
|
||||
|
||||
@ -162,6 +187,11 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
|
||||
stretch = attr.get("stretch", "")
|
||||
params = attr.get("params", {})
|
||||
|
||||
group_x = attr.get("group_x", 0.0)
|
||||
group_y = attr.get("group_y", 0.0)
|
||||
group_width = attr.get("group_width", 1.0)
|
||||
group_height = attr.get("group_height", 1.0)
|
||||
|
||||
overlap = params.get("overlap", 0.0)
|
||||
xy_ratio = params.get("xy-ratio", -1.0)
|
||||
y_padding = params.get("ypadding", 0.0)
|
||||
@ -180,16 +210,18 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
|
||||
if "xy" in stretch:
|
||||
s += " .size_horizontal = .stretch,\n"
|
||||
s += " .size_vertical = .stretch,\n"
|
||||
elif "!" in stretch:
|
||||
elif "!" in stretch or "^" in stretch:
|
||||
s += " .size_horizontal = .cover,\n"
|
||||
s += " .size_vertical = .fit,\n"
|
||||
elif "^" in stretch:
|
||||
s += " .size_horizontal = .cover,\n"
|
||||
s += " .size_vertical = .cover,\n"
|
||||
else:
|
||||
s += " .size_horizontal = .fit,\n"
|
||||
s += " .size_vertical = .fit,\n"
|
||||
|
||||
# `^` indicates that scaling should fill
|
||||
# the whole cell, not just the icon height.
|
||||
if "^" not in stretch:
|
||||
s += " .height = .icon,\n"
|
||||
|
||||
# There are two cases where we want to limit the constraint width to 1:
|
||||
# - If there's a `1` in the stretch mode string.
|
||||
# - If the stretch mode is `xy` and there's not an explicit `2`.
|
||||
@ -201,6 +233,15 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
|
||||
if valign is not None:
|
||||
s += f" .align_vertical = {valign},\n"
|
||||
|
||||
if group_width != 1.0:
|
||||
s += f" .group_width = {group_width:.16f},\n"
|
||||
if group_height != 1.0:
|
||||
s += f" .group_height = {group_height:.16f},\n"
|
||||
if group_x != 0.0:
|
||||
s += f" .group_x = {group_x:.16f},\n"
|
||||
if group_y != 0.0:
|
||||
s += f" .group_y = {group_y:.16f},\n"
|
||||
|
||||
# `overlap` and `ypadding` are mutually exclusive,
|
||||
# this is asserted in the nerd fonts patcher itself.
|
||||
if overlap:
|
||||
@ -223,16 +264,53 @@ def emit_zig_entry_multikey(codepoints: list[int], attr: PatchSetAttributeEntry)
|
||||
return s
|
||||
|
||||
|
||||
def generate_zig_switch_arms(patch_sets: list[PatchSet]) -> str:
|
||||
def generate_zig_switch_arms(
|
||||
patch_sets: list[PatchSet],
|
||||
nerd_font: TTFont,
|
||||
) -> str:
|
||||
cmap = nerd_font.getBestCmap()
|
||||
glyphs = nerd_font.getGlyphSet()
|
||||
|
||||
entries: dict[int, PatchSetAttributeEntry] = {}
|
||||
for entry in patch_sets:
|
||||
attributes = entry["Attributes"]
|
||||
|
||||
for cp in range(entry["SymStart"], entry["SymEnd"] + 1):
|
||||
entries[cp] = attributes["default"]
|
||||
entries[cp] = attributes["default"].copy()
|
||||
|
||||
entries |= {k: v for k, v in attributes.items() if isinstance(k, int)}
|
||||
|
||||
if entry["ScaleRules"] is not None and "ScaleGroups" in entry["ScaleRules"]:
|
||||
for group in entry["ScaleRules"]["ScaleGroups"]:
|
||||
xMin = math.inf
|
||||
yMin = math.inf
|
||||
xMax = -math.inf
|
||||
yMax = -math.inf
|
||||
individual_bounds: dict[int, tuple[int, int, int ,int]] = {}
|
||||
for cp in group:
|
||||
if cp not in cmap:
|
||||
continue
|
||||
glyph = glyphs[cmap[cp]]
|
||||
bounds = BoundsPen(glyphSet=glyphs)
|
||||
glyph.draw(bounds)
|
||||
individual_bounds[cp] = bounds.bounds
|
||||
xMin = min(bounds.bounds[0], xMin)
|
||||
yMin = min(bounds.bounds[1], yMin)
|
||||
xMax = max(bounds.bounds[2], xMax)
|
||||
yMax = max(bounds.bounds[3], yMax)
|
||||
group_width = xMax - xMin
|
||||
group_height = yMax - yMin
|
||||
for cp in group:
|
||||
if cp not in cmap or cp not in entries:
|
||||
continue
|
||||
this_bounds = individual_bounds[cp]
|
||||
this_width = this_bounds[2] - this_bounds[0]
|
||||
this_height = this_bounds[3] - this_bounds[1]
|
||||
entries[cp]["group_width"] = group_width / this_width
|
||||
entries[cp]["group_height"] = group_height / this_height
|
||||
entries[cp]["group_x"] = (this_bounds[0] - xMin) / group_width
|
||||
entries[cp]["group_y"] = (this_bounds[1] - yMin) / group_height
|
||||
|
||||
del entries[0]
|
||||
|
||||
# Group codepoints by attribute key
|
||||
@ -253,6 +331,10 @@ def generate_zig_switch_arms(patch_sets: list[PatchSet]) -> str:
|
||||
if __name__ == "__main__":
|
||||
project_root = Path(__file__).resolve().parents[2]
|
||||
|
||||
nf_path = sys.argv[1]
|
||||
|
||||
nerd_font = TTFont(nf_path)
|
||||
|
||||
patcher_path = project_root / "vendor" / "nerd-fonts" / "font-patcher.py"
|
||||
source = patcher_path.read_text(encoding="utf-8")
|
||||
patch_set = extract_patch_set_values(source)
|
||||
@ -272,5 +354,5 @@ const Constraint = @import("face.zig").RenderOptions.Constraint;
|
||||
pub fn getConstraint(cp: u21) Constraint {
|
||||
return switch (cp) {
|
||||
""")
|
||||
f.write(generate_zig_switch_arms(patch_set))
|
||||
f.write(generate_zig_switch_arms(patch_set, nerd_font))
|
||||
f.write("\n else => .none,\n };\n}\n")
|
||||
|
@ -195,7 +195,6 @@ pub fn renderGlyph(
|
||||
.offset_y = 0,
|
||||
.atlas_x = 0,
|
||||
.atlas_y = 0,
|
||||
.advance_x = 0,
|
||||
};
|
||||
|
||||
const metrics = self.metrics;
|
||||
@ -227,8 +226,6 @@ pub fn renderGlyph(
|
||||
.offset_y = @as(i32, @intCast(region.height +| canvas.clip_bottom)) - @as(i32, @intCast(padding_y)),
|
||||
.atlas_x = region.x,
|
||||
.atlas_y = region.y,
|
||||
.advance_x = @floatFromInt(width),
|
||||
.sprite = true,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,12 @@ const internal_os = @import("os/main.zig");
|
||||
|
||||
// Some comptime assertions that our C API depends on.
|
||||
comptime {
|
||||
assert(apprt.runtime == apprt.embedded);
|
||||
// We allow tests to reference this file because we unit test
|
||||
// some of the C API. At runtime though we should never get these
|
||||
// functions unless we are building libghostty.
|
||||
if (!builtin.is_test) {
|
||||
assert(apprt.runtime == apprt.embedded);
|
||||
}
|
||||
}
|
||||
|
||||
/// Global options so we can log. This is identical to main.
|
||||
@ -29,7 +34,9 @@ comptime {
|
||||
// These structs need to be referenced so the `export` functions
|
||||
// are truly exported by the C API lib.
|
||||
_ = @import("config.zig").CAPI;
|
||||
_ = apprt.runtime.CAPI;
|
||||
if (@hasDecl(apprt.runtime, "CAPI")) {
|
||||
_ = apprt.runtime.CAPI;
|
||||
}
|
||||
}
|
||||
|
||||
/// ghostty_info_s
|
||||
@ -46,6 +53,24 @@ const Info = extern struct {
|
||||
};
|
||||
};
|
||||
|
||||
/// ghostty_string_s
|
||||
pub const String = extern struct {
|
||||
ptr: ?[*]const u8,
|
||||
len: usize,
|
||||
|
||||
pub const empty: String = .{
|
||||
.ptr = null,
|
||||
.len = 0,
|
||||
};
|
||||
|
||||
pub fn fromSlice(slice: []const u8) String {
|
||||
return .{
|
||||
.ptr = slice.ptr,
|
||||
.len = slice.len,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Initialize ghostty global state.
|
||||
export fn ghostty_init(argc: usize, argv: [*][*:0]u8) c_int {
|
||||
assert(builtin.link_libc);
|
||||
@ -95,3 +120,8 @@ export fn ghostty_info() Info {
|
||||
export fn ghostty_translate(msgid: [*:0]const u8) [*:0]const u8 {
|
||||
return internal_os.i18n._(msgid);
|
||||
}
|
||||
|
||||
/// Free a string allocated by Ghostty.
|
||||
export fn ghostty_string_free(str: String) void {
|
||||
state.alloc.free(str.ptr.?[0..str.len]);
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ pub const locales = [_][:0]const u8{
|
||||
"ca_ES.UTF-8",
|
||||
"bg_BG.UTF-8",
|
||||
"ga_IE.UTF-8",
|
||||
"he_IL.UTF-8",
|
||||
};
|
||||
|
||||
/// Set for faster membership lookup of locales.
|
||||
|
@ -17,7 +17,7 @@ test "read /proc/sys/kernel/osrelease" {
|
||||
if (comptime builtin.os.tag != .linux) return null;
|
||||
const allocator = std.testing.allocator;
|
||||
|
||||
const kernel_info = try getKernelInfo(allocator);
|
||||
const kernel_info = getKernelInfo(allocator).?;
|
||||
defer allocator.free(kernel_info);
|
||||
|
||||
// Since we can't hardcode the info in tests, just check
|
||||
|
@ -2,6 +2,8 @@
|
||||
//! system. These aren't restricted to syscalls or low-level operations, but
|
||||
//! also OS-specific features and conventions.
|
||||
|
||||
const builtin = @import("builtin");
|
||||
|
||||
const dbus = @import("dbus.zig");
|
||||
const desktop = @import("desktop.zig");
|
||||
const env = @import("env.zig");
|
||||
@ -14,7 +16,7 @@ const openpkg = @import("open.zig");
|
||||
const pipepkg = @import("pipe.zig");
|
||||
const resourcesdir = @import("resourcesdir.zig");
|
||||
const systemd = @import("systemd.zig");
|
||||
const kernelInfo = @import("kernel_info.zig");
|
||||
const kernel_info = @import("kernel_info.zig");
|
||||
|
||||
// Namespaces
|
||||
pub const args = @import("args.zig");
|
||||
@ -59,8 +61,12 @@ pub const pipe = pipepkg.pipe;
|
||||
pub const resourcesDir = resourcesdir.resourcesDir;
|
||||
pub const ResourcesDir = resourcesdir.ResourcesDir;
|
||||
pub const ShellEscapeWriter = shell.ShellEscapeWriter;
|
||||
pub const getKernelInfo = kernelInfo.getKernelInfo;
|
||||
pub const getKernelInfo = kernel_info.getKernelInfo;
|
||||
|
||||
test {
|
||||
_ = i18n;
|
||||
|
||||
if (comptime builtin.os.tag == .linux) {
|
||||
_ = kernel_info;
|
||||
}
|
||||
}
|
||||
|
@ -63,3 +63,136 @@ pub fn launchedBySystemd() bool {
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
/// systemd notifications. Used by Ghostty to inform systemd of the state of the
|
||||
/// process. Currently only used to notify systemd that we are ready and that
|
||||
/// configuration reloading has started.
|
||||
///
|
||||
/// See: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html
|
||||
///
|
||||
/// These functions were re-implemented in Zig instead of using the `libsystemd`
|
||||
/// library to avoid the complexity of another external dependency, as well as
|
||||
/// to take advantage of Zig features like `comptime` to ensure minimal impact
|
||||
/// on non-Linux systems (like FreeBSD) that will never support `systemd`.
|
||||
///
|
||||
/// Linux systems that do not use `systemd` should not be impacted as they
|
||||
/// should never start Ghostty with the `NOTIFY_SOCKET` environment variable set
|
||||
/// and these functions essentially become a no-op.
|
||||
///
|
||||
/// See `systemd`'s [Interface Portability and Stability Promise](https://systemd.io/PORTABILITY_AND_STABILITY/)
|
||||
/// for assurances that the interfaces used here will be supported and stable for
|
||||
/// the long term.
|
||||
pub const notify = struct {
|
||||
/// Send the given message to the UNIX socket specified in the NOTIFY_SOCKET
|
||||
/// environment variable. If there NOTIFY_SOCKET environment variable does
|
||||
/// not exist then no message is sent.
|
||||
fn send(message: []const u8) void {
|
||||
// systemd is Linux-only so this is a no-op anywhere else
|
||||
if (comptime builtin.os.tag != .linux) return;
|
||||
|
||||
// Get the socket address that should receive notifications.
|
||||
const socket_path = std.posix.getenv("NOTIFY_SOCKET") orelse return;
|
||||
|
||||
// If the socket address is an empty string return.
|
||||
if (socket_path.len == 0) return;
|
||||
|
||||
// The socket address must be a path or an abstract socket.
|
||||
if (socket_path[0] != '/' and socket_path[0] != '@') {
|
||||
log.warn("only AF_UNIX sockets with path or abstract namespace addresses are supported!", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
var socket_address: std.os.linux.sockaddr.un = undefined;
|
||||
|
||||
// Error out if the supplied socket path is too long.
|
||||
if (socket_address.path.len < socket_path.len) {
|
||||
log.warn("NOTIFY_SOCKET path is too long!", .{});
|
||||
return;
|
||||
}
|
||||
|
||||
socket_address.family = std.os.linux.AF.UNIX;
|
||||
|
||||
@memcpy(socket_address.path[0..socket_path.len], socket_path);
|
||||
socket_address.path[socket_path.len] = 0;
|
||||
|
||||
const socket: std.os.linux.socket_t = socket: {
|
||||
const rc = std.os.linux.socket(
|
||||
std.os.linux.AF.UNIX,
|
||||
std.os.linux.SOCK.DGRAM | std.os.linux.SOCK.CLOEXEC,
|
||||
0,
|
||||
);
|
||||
switch (std.os.linux.E.init(rc)) {
|
||||
.SUCCESS => break :socket @intCast(rc),
|
||||
else => |e| {
|
||||
log.warn("creating socket failed: {s}", .{@tagName(e)});
|
||||
return;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
defer _ = std.os.linux.close(socket);
|
||||
|
||||
connect: {
|
||||
const rc = std.os.linux.connect(
|
||||
socket,
|
||||
&socket_address,
|
||||
@offsetOf(std.os.linux.sockaddr.un, "path") + socket_address.path.len,
|
||||
);
|
||||
switch (std.os.linux.E.init(rc)) {
|
||||
.SUCCESS => break :connect,
|
||||
else => |e| {
|
||||
log.warn("unable to connect to notify socket: {s}", .{@tagName(e)});
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
write: {
|
||||
const rc = std.os.linux.write(socket, message.ptr, message.len);
|
||||
switch (std.os.linux.E.init(rc)) {
|
||||
.SUCCESS => {
|
||||
const written = rc;
|
||||
if (written < message.len) {
|
||||
log.warn("short write to notify socket: {d} < {d}", .{ rc, message.len });
|
||||
return;
|
||||
}
|
||||
break :write;
|
||||
},
|
||||
else => |e| {
|
||||
log.warn("unable to write to notify socket: {s}", .{@tagName(e)});
|
||||
return;
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tell systemd that we are ready or that we are finished reloading.
|
||||
/// See: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#READY=1
|
||||
pub fn ready() void {
|
||||
if (comptime builtin.os.tag != .linux) return;
|
||||
|
||||
send("READY=1");
|
||||
}
|
||||
|
||||
/// Tell systemd that we have started reloading our configuration.
|
||||
/// See: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#RELOADING=1
|
||||
/// and: https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#MONOTONIC_USEC=%E2%80%A6
|
||||
pub fn reloading() void {
|
||||
if (comptime builtin.os.tag != .linux) return;
|
||||
|
||||
const ts = std.posix.clock_gettime(.MONOTONIC) catch |err| {
|
||||
log.err("unable to get MONOTONIC clock: {}", .{err});
|
||||
return;
|
||||
};
|
||||
|
||||
const now = ts.sec * std.time.us_per_s + @divFloor(ts.nsec, std.time.ns_per_us);
|
||||
|
||||
var buffer: [64]u8 = undefined;
|
||||
const message = std.fmt.bufPrint(&buffer, "RELOADING=1\nMONOTONIC_USEC={d}", .{now}) catch |err| {
|
||||
log.err("unable to format reloading message: {}", .{err});
|
||||
return;
|
||||
};
|
||||
|
||||
send(message);
|
||||
}
|
||||
};
|
||||
|
@ -95,6 +95,76 @@ if [[ "$GHOSTTY_SHELL_FEATURES" == *"sudo"* && -n "$TERMINFO" ]]; then
|
||||
}
|
||||
fi
|
||||
|
||||
# SSH Integration
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
|
||||
ssh() {
|
||||
builtin local ssh_term ssh_opts
|
||||
ssh_term="xterm-256color"
|
||||
ssh_opts=()
|
||||
|
||||
# Configure environment variables for remote session
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
|
||||
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
|
||||
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
|
||||
fi
|
||||
|
||||
# Install terminfo on remote host if needed
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-terminfo* ]]; then
|
||||
builtin local ssh_user ssh_hostname
|
||||
|
||||
while IFS=' ' read -r ssh_key ssh_value; do
|
||||
case "$ssh_key" in
|
||||
user) ssh_user="$ssh_value" ;;
|
||||
hostname) ssh_hostname="$ssh_value" ;;
|
||||
esac
|
||||
[[ -n "$ssh_user" && -n "$ssh_hostname" ]] && break
|
||||
done < <(builtin command ssh -G "$@" 2>/dev/null)
|
||||
|
||||
if [[ -n "$ssh_hostname" ]]; then
|
||||
builtin local ssh_target="${ssh_user}@${ssh_hostname}"
|
||||
|
||||
# Check if terminfo is already cached
|
||||
if "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1; then
|
||||
ssh_term="xterm-ghostty"
|
||||
elif builtin command -v infocmp >/dev/null 2>&1; then
|
||||
builtin local ssh_terminfo ssh_cpath_dir ssh_cpath
|
||||
|
||||
ssh_terminfo=$(infocmp -0 -x xterm-ghostty 2>/dev/null)
|
||||
|
||||
if [[ -n "$ssh_terminfo" ]]; then
|
||||
builtin echo "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
|
||||
|
||||
ssh_cpath_dir=$(mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null) || ssh_cpath_dir="/tmp/ghostty-ssh-$ssh_user.$$"
|
||||
ssh_cpath="$ssh_cpath_dir/socket"
|
||||
|
||||
if builtin echo "$ssh_terminfo" | builtin command ssh -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s "$@" '
|
||||
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
|
||||
command -v tic >/dev/null 2>&1 || exit 1
|
||||
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
|
||||
exit 1
|
||||
' 2>/dev/null; then
|
||||
ssh_term="xterm-ghostty"
|
||||
ssh_opts+=(-o "ControlPath=$ssh_cpath")
|
||||
|
||||
# Cache successful installation
|
||||
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1 || true
|
||||
else
|
||||
builtin echo "Warning: Failed to install terminfo." >&2
|
||||
fi
|
||||
else
|
||||
builtin echo "Warning: Could not generate terminfo data." >&2
|
||||
fi
|
||||
else
|
||||
builtin echo "Warning: ghostty command not available for cache management." >&2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Execute SSH with TERM environment variable
|
||||
TERM="$ssh_term" builtin command ssh "${ssh_opts[@]}" "$@"
|
||||
}
|
||||
fi
|
||||
|
||||
# Import bash-preexec, safe to do multiple times
|
||||
builtin source "$(dirname -- "${BASH_SOURCE[0]}")/bash-preexec.sh"
|
||||
|
||||
|
@ -98,6 +98,95 @@
|
||||
(external sudo) $@args
|
||||
}
|
||||
|
||||
# SSH Integration
|
||||
use str
|
||||
|
||||
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-) {
|
||||
fn ssh {|@args|
|
||||
var ssh-term = "xterm-256color"
|
||||
var ssh-opts = []
|
||||
|
||||
# Configure environment variables for remote session
|
||||
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-env) {
|
||||
set ssh-opts = (conj $ssh-opts
|
||||
-o "SetEnv COLORTERM=truecolor"
|
||||
-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION"
|
||||
)
|
||||
}
|
||||
|
||||
# Install terminfo on remote host if needed
|
||||
if (str:contains $E:GHOSTTY_SHELL_FEATURES ssh-terminfo) {
|
||||
var ssh-user = ""
|
||||
var ssh-hostname = ""
|
||||
|
||||
# Parse ssh config
|
||||
var ssh-config = (external ssh -G $@args 2>/dev/null | slurp)
|
||||
for line (str:split "\n" $ssh-config) {
|
||||
var parts = (str:split " " $line)
|
||||
if (> (count $parts) 1) {
|
||||
var ssh-key = $parts[0]
|
||||
var ssh-value = $parts[1]
|
||||
if (eq $ssh-key user) {
|
||||
set ssh-user = $ssh-value
|
||||
} elif (eq $ssh-key hostname) {
|
||||
set ssh-hostname = $ssh-value
|
||||
}
|
||||
if (and (not-eq $ssh-user "") (not-eq $ssh-hostname "")) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (not-eq $ssh-hostname "") {
|
||||
var ssh-target = $ssh-user"@"$ssh-hostname
|
||||
|
||||
# Check if terminfo is already cached
|
||||
if (and (has-external ghostty) (bool ?(external ghostty +ssh-cache --host=$ssh-target >/dev/null 2>&1))) {
|
||||
set ssh-term = "xterm-ghostty"
|
||||
} elif (has-external infocmp) {
|
||||
var ssh-terminfo = (external infocmp -0 -x xterm-ghostty 2>/dev/null | slurp)
|
||||
|
||||
if (not-eq $ssh-terminfo "") {
|
||||
echo "Setting up xterm-ghostty terminfo on "$ssh-hostname"..." >&2
|
||||
|
||||
var ssh-cpath-dir = ""
|
||||
try {
|
||||
set ssh-cpath-dir = (external mktemp -d "/tmp/ghostty-ssh-"$ssh-user".XXXXXX" 2>/dev/null | slurp)
|
||||
} catch {
|
||||
set ssh-cpath-dir = "/tmp/ghostty-ssh-"$ssh-user"."(randint 10000 99999)
|
||||
}
|
||||
var ssh-cpath = $ssh-cpath-dir"/socket"
|
||||
|
||||
if (bool ?(echo $ssh-terminfo | external ssh $@ssh-opts -o ControlMaster=yes -o ControlPath=$ssh-cpath -o ControlPersist=60s $@args '
|
||||
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
|
||||
command -v tic >/dev/null 2>&1 || exit 1
|
||||
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
|
||||
exit 1
|
||||
' 2>/dev/null)) {
|
||||
set ssh-term = "xterm-ghostty"
|
||||
set ssh-opts = (conj $ssh-opts -o ControlPath=$ssh-cpath)
|
||||
|
||||
# Cache successful installation
|
||||
if (has-external ghostty) {
|
||||
external ghostty +ssh-cache --add=$ssh-target >/dev/null 2>&1
|
||||
}
|
||||
} else {
|
||||
echo "Warning: Failed to install terminfo." >&2
|
||||
}
|
||||
} else {
|
||||
echo "Warning: Could not generate terminfo data." >&2
|
||||
}
|
||||
} else {
|
||||
echo "Warning: ghostty command not available for cache management." >&2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Execute SSH with TERM environment variable
|
||||
external E:TERM=$ssh-term ssh $@ssh-opts $@args
|
||||
}
|
||||
}
|
||||
|
||||
defer {
|
||||
mark-prompt-start
|
||||
report-pwd
|
||||
|
@ -86,6 +86,89 @@ function __ghostty_setup --on-event fish_prompt -d "Setup ghostty integration"
|
||||
end
|
||||
end
|
||||
|
||||
# SSH Integration
|
||||
set -l features (string split ',' -- "$GHOSTTY_SHELL_FEATURES")
|
||||
if contains ssh-env $features; or contains ssh-terminfo $features
|
||||
function ssh --wraps=ssh --description "SSH wrapper with Ghostty integration"
|
||||
set -l features (string split ',' -- "$GHOSTTY_SHELL_FEATURES")
|
||||
set -l ssh_term "xterm-256color"
|
||||
set -l ssh_opts
|
||||
|
||||
# Configure environment variables for remote session
|
||||
if contains ssh-env $features
|
||||
set -a ssh_opts -o "SetEnv COLORTERM=truecolor"
|
||||
set -a ssh_opts -o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION"
|
||||
end
|
||||
|
||||
# Install terminfo on remote host if needed
|
||||
if contains ssh-terminfo $features
|
||||
set -l ssh_user
|
||||
set -l ssh_hostname
|
||||
|
||||
for line in (command ssh -G $argv 2>/dev/null)
|
||||
set -l parts (string split ' ' -- $line)
|
||||
if test (count $parts) -ge 2
|
||||
switch $parts[1]
|
||||
case user
|
||||
set ssh_user $parts[2]
|
||||
case hostname
|
||||
set ssh_hostname $parts[2]
|
||||
end
|
||||
if test -n "$ssh_user"; and test -n "$ssh_hostname"
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if test -n "$ssh_hostname"
|
||||
set -l ssh_target "$ssh_user@$ssh_hostname"
|
||||
|
||||
# Check if terminfo is already cached
|
||||
if test -x "$GHOSTTY_BIN_DIR/ghostty"; and "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1
|
||||
set ssh_term "xterm-ghostty"
|
||||
else if command -q infocmp
|
||||
set -l ssh_terminfo
|
||||
set -l ssh_cpath_dir
|
||||
set -l ssh_cpath
|
||||
|
||||
set ssh_terminfo (infocmp -0 -x xterm-ghostty 2>/dev/null)
|
||||
|
||||
if test -n "$ssh_terminfo"
|
||||
echo "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
|
||||
|
||||
set ssh_cpath_dir (mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null; or echo "/tmp/ghostty-ssh-$ssh_user."(random))
|
||||
set ssh_cpath "$ssh_cpath_dir/socket"
|
||||
|
||||
if echo "$ssh_terminfo" | command ssh $ssh_opts -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s $argv '
|
||||
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
|
||||
command -v tic >/dev/null 2>&1 || exit 1
|
||||
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
|
||||
exit 1
|
||||
' 2>/dev/null
|
||||
set ssh_term "xterm-ghostty"
|
||||
set -a ssh_opts -o "ControlPath=$ssh_cpath"
|
||||
|
||||
# Cache successful installation
|
||||
if test -x "$GHOSTTY_BIN_DIR/ghostty"
|
||||
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1; or true
|
||||
end
|
||||
else
|
||||
echo "Warning: Failed to install terminfo." >&2
|
||||
end
|
||||
else
|
||||
echo "Warning: Could not generate terminfo data." >&2
|
||||
end
|
||||
else
|
||||
echo "Warning: ghostty command not available for cache management." >&2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Execute SSH with TERM environment variable
|
||||
env TERM="$ssh_term" command ssh $ssh_opts $argv
|
||||
end
|
||||
end
|
||||
|
||||
# Setup prompt marking
|
||||
function __ghostty_mark_prompt_start --on-event fish_prompt --on-event fish_cancel --on-event fish_posterror
|
||||
# If we never got the output end event, then we need to send it now.
|
||||
|
@ -244,6 +244,79 @@ _ghostty_deferred_init() {
|
||||
}
|
||||
fi
|
||||
|
||||
# SSH Integration
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-* ]]; then
|
||||
ssh() {
|
||||
emulate -L zsh
|
||||
setopt local_options no_glob_subst
|
||||
|
||||
local ssh_term ssh_opts
|
||||
ssh_term="xterm-256color"
|
||||
ssh_opts=()
|
||||
|
||||
# Configure environment variables for remote session
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-env* ]]; then
|
||||
ssh_opts+=(-o "SetEnv COLORTERM=truecolor")
|
||||
ssh_opts+=(-o "SendEnv TERM_PROGRAM TERM_PROGRAM_VERSION")
|
||||
fi
|
||||
|
||||
# Install terminfo on remote host if needed
|
||||
if [[ "$GHOSTTY_SHELL_FEATURES" == *ssh-terminfo* ]]; then
|
||||
local ssh_user ssh_hostname
|
||||
|
||||
while IFS=' ' read -r ssh_key ssh_value; do
|
||||
case "$ssh_key" in
|
||||
user) ssh_user="$ssh_value" ;;
|
||||
hostname) ssh_hostname="$ssh_value" ;;
|
||||
esac
|
||||
[[ -n "$ssh_user" && -n "$ssh_hostname" ]] && break
|
||||
done < <(command ssh -G "$@" 2>/dev/null)
|
||||
|
||||
if [[ -n "$ssh_hostname" ]]; then
|
||||
local ssh_target="${ssh_user}@${ssh_hostname}"
|
||||
|
||||
# Check if terminfo is already cached
|
||||
if "$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --host="$ssh_target" >/dev/null 2>&1; then
|
||||
ssh_term="xterm-ghostty"
|
||||
elif (( $+commands[infocmp] )); then
|
||||
local ssh_terminfo ssh_cpath_dir ssh_cpath
|
||||
|
||||
ssh_terminfo=$(infocmp -0 -x xterm-ghostty 2>/dev/null)
|
||||
|
||||
if [[ -n "$ssh_terminfo" ]]; then
|
||||
print "Setting up xterm-ghostty terminfo on $ssh_hostname..." >&2
|
||||
|
||||
ssh_cpath_dir=$(mktemp -d "/tmp/ghostty-ssh-$ssh_user.XXXXXX" 2>/dev/null) || ssh_cpath_dir="/tmp/ghostty-ssh-$ssh_user.$$"
|
||||
ssh_cpath="$ssh_cpath_dir/socket"
|
||||
|
||||
if print "$ssh_terminfo" | command ssh "${ssh_opts[@]}" -o ControlMaster=yes -o ControlPath="$ssh_cpath" -o ControlPersist=60s "$@" '
|
||||
infocmp xterm-ghostty >/dev/null 2>&1 && exit 0
|
||||
command -v tic >/dev/null 2>&1 || exit 1
|
||||
mkdir -p ~/.terminfo 2>/dev/null && tic -x - 2>/dev/null && exit 0
|
||||
exit 1
|
||||
' 2>/dev/null; then
|
||||
ssh_term="xterm-ghostty"
|
||||
ssh_opts+=(-o "ControlPath=$ssh_cpath")
|
||||
|
||||
# Cache successful installation
|
||||
"$GHOSTTY_BIN_DIR/ghostty" +ssh-cache --add="$ssh_target" >/dev/null 2>&1 || true
|
||||
else
|
||||
print "Warning: Failed to install terminfo." >&2
|
||||
fi
|
||||
else
|
||||
print "Warning: Could not generate terminfo data." >&2
|
||||
fi
|
||||
else
|
||||
print "Warning: ghostty command not available for cache management." >&2
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Execute SSH with TERM environment variable
|
||||
TERM="$ssh_term" command ssh "${ssh_opts[@]}" "$@"
|
||||
}
|
||||
fi
|
||||
|
||||
# Some zsh users manually run `source ~/.zshrc` in order to apply rc file
|
||||
# changes to the current shell. This is a terrible practice that breaks many
|
||||
# things, including our shell integration. For example, Oh My Zsh and Prezto
|
||||
|
@ -154,15 +154,12 @@ pub const Style = struct {
|
||||
|
||||
.palette => |idx| palette: {
|
||||
if (self.flags.bold) {
|
||||
if (opts.bold) |bold| switch (bold) {
|
||||
.color => |v| break :palette v.toTerminalRGB(),
|
||||
.bright => {
|
||||
const bright_offset = @intFromEnum(color.Name.bright_black);
|
||||
if (idx < bright_offset) {
|
||||
break :palette opts.palette[idx + bright_offset];
|
||||
}
|
||||
},
|
||||
};
|
||||
if (opts.bold) |_| {
|
||||
const bright_offset = @intFromEnum(color.Name.bright_black);
|
||||
if (idx < bright_offset) {
|
||||
break :palette opts.palette[idx + bright_offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break :palette opts.palette[idx];
|
||||
|
@ -177,10 +177,28 @@ pub fn setupFeatures(
|
||||
};
|
||||
var buffer = try std.BoundedArray(u8, capacity).init(0);
|
||||
|
||||
inline for (fields) |field| {
|
||||
if (@field(features, field.name)) {
|
||||
// Sort the fields so that the output is deterministic. This is
|
||||
// done at comptime so it has no runtime cost
|
||||
const fields_sorted: [fields.len][]const u8 = comptime fields: {
|
||||
var fields_sorted: [fields.len][]const u8 = undefined;
|
||||
for (fields, 0..) |field, i| fields_sorted[i] = field.name;
|
||||
std.mem.sortUnstable(
|
||||
[]const u8,
|
||||
&fields_sorted,
|
||||
{},
|
||||
(struct {
|
||||
fn lessThan(_: void, lhs: []const u8, rhs: []const u8) bool {
|
||||
return std.ascii.orderIgnoreCase(lhs, rhs) == .lt;
|
||||
}
|
||||
}).lessThan,
|
||||
);
|
||||
break :fields fields_sorted;
|
||||
};
|
||||
|
||||
inline for (fields_sorted) |name| {
|
||||
if (@field(features, name)) {
|
||||
if (buffer.len > 0) try buffer.append(',');
|
||||
try buffer.appendSlice(field.name);
|
||||
try buffer.appendSlice(name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -201,8 +219,8 @@ test "setup features" {
|
||||
var env = EnvMap.init(alloc);
|
||||
defer env.deinit();
|
||||
|
||||
try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true });
|
||||
try testing.expectEqualStrings("cursor,sudo,title", env.get("GHOSTTY_SHELL_FEATURES").?);
|
||||
try setupFeatures(&env, .{ .cursor = true, .sudo = true, .title = true, .@"ssh-env" = true, .@"ssh-terminfo" = true });
|
||||
try testing.expectEqualStrings("cursor,ssh-env,ssh-terminfo,sudo,title", env.get("GHOSTTY_SHELL_FEATURES").?);
|
||||
}
|
||||
|
||||
// Test: all features disabled
|
||||
@ -210,7 +228,7 @@ test "setup features" {
|
||||
var env = EnvMap.init(alloc);
|
||||
defer env.deinit();
|
||||
|
||||
try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false });
|
||||
try setupFeatures(&env, .{ .cursor = false, .sudo = false, .title = false, .@"ssh-env" = false, .@"ssh-terminfo" = false });
|
||||
try testing.expect(env.get("GHOSTTY_SHELL_FEATURES") == null);
|
||||
}
|
||||
|
||||
@ -219,8 +237,8 @@ test "setup features" {
|
||||
var env = EnvMap.init(alloc);
|
||||
defer env.deinit();
|
||||
|
||||
try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false });
|
||||
try testing.expectEqualStrings("sudo", env.get("GHOSTTY_SHELL_FEATURES").?);
|
||||
try setupFeatures(&env, .{ .cursor = false, .sudo = true, .title = false, .@"ssh-env" = true, .@"ssh-terminfo" = false });
|
||||
try testing.expectEqualStrings("ssh-env,sudo", env.get("GHOSTTY_SHELL_FEATURES").?);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user