Update: Terminal Fonts

This commit is contained in:
Hariharan Mudaliar 2026-03-11 13:29:10 +05:30
commit 44d5ca2573
No known key found for this signature in database
GPG key ID: 025583EB0BE5640E
4 changed files with 134 additions and 7 deletions

View file

@ -1661,6 +1661,10 @@
}
}
},
"±10 Seconds" : {
"comment" : "Displayed as the name of the music skip behavior option.",
"isCommentAutoGenerated" : true
},
"0" : {
"comment" : "A label displayed in a circular gauge to indicate the minimum battery level.",
"isCommentAutoGenerated" : true,
@ -2013,6 +2017,10 @@
}
}
},
"Accent" : {
"comment" : "Display name for the \"Accent\" caps lock indicator tint mode.",
"isCommentAutoGenerated" : true
},
"Accent color" : {
"localizations" : {
"ar" : {
@ -2358,6 +2366,10 @@
}
}
},
"Adaptive gradient" : {
"comment" : "Name of the timer icon color mode option that uses an adaptive gradient.",
"isCommentAutoGenerated" : true
},
"Add" : {
"localizations" : {
"ar" : {
@ -3977,6 +3989,10 @@
}
}
},
"Apple Music" : {
"comment" : "Names for the different media player types.",
"isCommentAutoGenerated" : true
},
"Applies the notch-style parallax effect to the lock screen media widget album art." : {
"localizations" : {
"pt-BR" : {
@ -4409,6 +4425,10 @@
}
}
},
"Bar" : {
"comment" : "Localized name for the \"Bar\" timer progress style.",
"isCommentAutoGenerated" : true
},
"Battery" : {
"localizations" : {
"ar" : {
@ -8798,6 +8818,10 @@
}
}
},
"Digital" : {
"comment" : "The display name for the \"Digital\" reminder presentation style.",
"isCommentAutoGenerated" : true
},
"Dimensions" : {
"localizations" : {
"pt-BR" : {
@ -11451,6 +11475,9 @@
}
}
}
},
"Font family" : {
},
"Font size" : {
"comment" : "A label displayed above a slider that controls the font size of the terminal",
@ -12338,6 +12365,10 @@
}
}
},
"Green" : {
"comment" : "Display name for the \"Green\" Caps Lock Indicator Tint Mode.",
"isCommentAutoGenerated" : true
},
"Height:" : {
"extractionState" : "stale",
"localizations" : {
@ -16121,7 +16152,6 @@
}
},
"Minutes" : {
"extractionState" : "stale",
"localizations" : {
"fr" : {
"stringUnit" : {
@ -18353,6 +18383,10 @@
}
}
},
"Now Playing" : {
"comment" : "Localized name for each media controller type.",
"isCommentAutoGenerated" : true
},
"Number of lines kept in the scrollback buffer. Higher values use more memory." : {
},
@ -18755,6 +18789,10 @@
}
}
},
"Panel" : {
"comment" : "Name for the \"Panel\" clipboard display mode.",
"isCommentAutoGenerated" : true
},
"Panel mode shows clipboard in a floating window near the notch." : {
"comment" : "A description of the \"Panel\" clipboard display mode.",
"isCommentAutoGenerated" : true,
@ -20456,6 +20494,10 @@
}
}
},
"Ring" : {
"comment" : "Localized name for the \"Ring\" timer progress style.",
"isCommentAutoGenerated" : true
},
"Rotation:" : {
"extractionState" : "stale",
"localizations" : {
@ -21300,6 +21342,10 @@
}
}
},
"Separate Tab" : {
"comment" : "Name of the clipboard display mode option that opens the clipboard in a separate tab.",
"isCommentAutoGenerated" : true
},
"Separate Tab mode integrates Copied Items and Notes into a single view. If both are enabled, Notes appear on the right and Clipboard on the left." : {
"comment" : "A description of the \"Separate Tab\" clipboard display mode.",
"isCommentAutoGenerated" : true,
@ -22391,6 +22437,14 @@
}
}
},
"Shows screen assistant as a dropdown attached to the AI button" : {
"comment" : "Description of the \"popover\" display mode for the screen assistant.",
"isCommentAutoGenerated" : true
},
"Shows screen assistant in a floating panel near the notch" : {
"comment" : "Description of the \"Panel\" screen assistant display mode.",
"isCommentAutoGenerated" : true
},
"Shows the model's reasoning process before the final answer" : {
"localizations" : {
"fr" : {
@ -22465,6 +22519,10 @@
}
}
},
"Skip forward or backward by ten seconds" : {
"comment" : "Description of the \"Skip forward or backward by ten seconds\" music skip behavior option.",
"isCommentAutoGenerated" : true
},
"Slider color" : {
"localizations" : {
"ar" : {
@ -23033,6 +23091,10 @@
}
}
},
"Spotify" : {
"comment" : "Name of a media controller type for Spotify.",
"isCommentAutoGenerated" : true
},
"Square" : {
"localizations" : {
"ar" : {
@ -23145,6 +23207,10 @@
},
"Standard notch media controls are hidden. Re-enable the toggle above to restore them." : {
},
"Standard previous/next track controls" : {
"comment" : "Description of a music skip behavior option that uses standard previous/next track controls.",
"isCommentAutoGenerated" : true
},
"Start" : {
"localizations" : {
@ -23865,6 +23931,9 @@
}
}
}
},
"System Monospaced" : {
},
"System Performance Monitor" : {
"extractionState" : "stale",
@ -24549,6 +24618,10 @@
},
"shouldTranslate" : false
},
"Track Skip" : {
"comment" : "Name of the music skip behavior option that skips to the next track.",
"isCommentAutoGenerated" : true
},
"Transform" : {
"extractionState" : "stale",
"localizations" : {
@ -26557,6 +26630,10 @@
"comment" : "A footer note explaining the app's funding.",
"isCommentAutoGenerated" : true
},
"Youtube Music" : {
"comment" : "Name for the \"Youtube Music\" media controller type in settings.",
"isCommentAutoGenerated" : true
},
"YouTube Music requires this third-party app to be installed: " : {
"localizations" : {
"ar" : {

View file

@ -7295,6 +7295,7 @@ struct TerminalSettings: View {
@ObservedObject var terminalManager = TerminalManager.shared
@Default(.enableTerminalFeature) var enableTerminalFeature
@Default(.terminalShellPath) var terminalShellPath
@Default(.terminalFontFamily) var terminalFontFamily
@Default(.terminalFontSize) var terminalFontSize
@Default(.terminalOpacity) var terminalOpacity
@Default(.terminalMaxHeightFraction) var terminalMaxHeightFraction
@ -7315,6 +7316,21 @@ struct TerminalSettings: View {
"\(Int(terminalMaxHeightFraction * 100))% of screen"
}
/// All monospaced font families available on the system.
private var monospacedFontFamilies: [String] {
NSFontManager.shared.availableFontFamilies.filter { family in
guard let font = NSFont(name: family, size: 12) else { return false }
return font.isFixedPitch
|| font.fontDescriptor.symbolicTraits.contains(.monoSpace)
}
.sorted()
}
/// Display name for the font picker — shows "System Monospaced" when no custom font is set.
private var fontDisplayName: String {
terminalFontFamily.isEmpty ? "System Monospaced" : terminalFontFamily
}
private var cursorStyleBinding: Binding<TerminalCursorStyleOption> {
Binding(
get: { TerminalCursorStyleOption(rawValue: terminalCursorStyle) ?? .blinkBlock },
@ -7365,6 +7381,20 @@ struct TerminalSettings: View {
// MARK: Appearance
Section {
Picker("Font family", selection: $terminalFontFamily) {
Text("System Monospaced").tag("")
Divider()
ForEach(monospacedFontFamilies, id: \.self) { family in
Text(family)
.font(.custom(family, size: 13))
.tag(family)
}
}
.onChange(of: terminalFontFamily) { _, newValue in
terminalManager.applyFontFamily(newValue)
}
.settingsHighlight(id: highlightID("Font family"))
VStack(alignment: .leading, spacing: 8) {
HStack {
Text("Font size")

View file

@ -181,15 +181,28 @@ class TerminalManager: ObservableObject {
terminalTitle = title
}
// MARK: - Font Resolution
/// Resolves the terminal font from the user's chosen family and size.
///
/// - If `family` is empty, returns the system monospaced font.
/// - Otherwise tries `NSFont(name:size:)` and falls back to system monospaced
/// when the name is invalid or the font is not installed.
private func resolveFont(family: String, size: CGFloat) -> NSFont {
if !family.isEmpty, let custom = NSFont(name: family, size: size) {
return custom
}
return NSFont.monospacedSystemFont(ofSize: size, weight: .regular)
}
// MARK: - Settings Application
/// Applies all persisted settings to a terminal view at creation time.
private func applyAllSettings(to view: LocalProcessTerminalView) {
// Font
let fontSize = CGFloat(Defaults[.terminalFontSize])
if let font = NSFont.monospacedSystemFont(ofSize: fontSize, weight: .regular) as NSFont? {
view.font = font
}
let fontFamily = Defaults[.terminalFontFamily]
view.font = resolveFont(family: fontFamily, size: fontSize)
// Opacity
view.layer?.opacity = Float(Defaults[.terminalOpacity])
@ -220,9 +233,15 @@ class TerminalManager: ObservableObject {
/// Updates font size on the live terminal view.
func applyFontSize(_ size: Double) {
guard let view = terminalView else { return }
if let font = NSFont.monospacedSystemFont(ofSize: CGFloat(size), weight: .regular) as NSFont? {
view.font = font
}
let fontFamily = Defaults[.terminalFontFamily]
view.font = resolveFont(family: fontFamily, size: CGFloat(size))
}
/// Updates font family on the live terminal view.
func applyFontFamily(_ family: String) {
guard let view = terminalView else { return }
let fontSize = CGFloat(Defaults[.terminalFontSize])
view.font = resolveFont(family: family, size: fontSize)
}
/// Updates opacity on the live terminal view.

View file

@ -915,6 +915,7 @@ extension Defaults.Keys {
// MARK: Terminal Feature
static let enableTerminalFeature = Key<Bool>("enableTerminalFeature", default: false)
static let terminalShellPath = Key<String>("terminalShellPath", default: "/bin/zsh")
static let terminalFontFamily = Key<String>("terminalFontFamily", default: "")
static let terminalFontSize = Key<Double>("terminalFontSize", default: 12.0)
static let terminalOpacity = Key<Double>("terminalOpacity", default: 1.0)
static let terminalMaxHeightFraction = Key<Double>("terminalMaxHeightFraction", default: 0.4)