ohmu
·
2026-10-15
1#include "terminalfont.h"
2#include "common/font.h"
3#include "detection/terminalshell/terminalshell.h"
4#include "common/apple/osascript.h"
5
6#include <stdlib.h>
7#include <string.h>
8#import <Foundation/Foundation.h>
9
10static void detectIterm2(FFTerminalFontResult* terminalFont)
11{
12 const char* profile = getenv("ITERM_PROFILE");
13 if (profile == nullptr)
14 {
15 ffStrbufAppendS(&terminalFont->error, "environment variable ITERM_PROFILE not set");
16 return;
17 }
18
19 NSError* error;
20 NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/com.googlecode.iterm2.plist", instance.state.platform.homeDir.chars];
21 NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
22 error:&error];
23 if(error)
24 {
25 ffStrbufAppendS(&terminalFont->error, error.localizedDescription.UTF8String);
26 return;
27 }
28
29 for(NSDictionary* bookmark in dict[@"New Bookmarks"])
30 {
31 if(![bookmark[@"Name"] isEqualToString:@(profile)])
32 continue;
33
34 NSString* normalFont = bookmark[@"Normal Font"];
35 if(!normalFont)
36 {
37 ffStrbufAppendF(&terminalFont->error, "`Normal Font` key in profile `%s` doesn't exist", profile);
38 return;
39 }
40 ffFontInitWithSpace(&terminalFont->font, normalFont.UTF8String);
41
42 NSNumber* useNonAsciiFont = bookmark[@"Use Non-ASCII Font"];
43 if(useNonAsciiFont.boolValue)
44 {
45 NSString* nonAsciiFont = bookmark[@"Non Ascii Font"];
46 if (nonAsciiFont)
47 ffFontInitWithSpace(&terminalFont->fallback, nonAsciiFont.UTF8String);
48 }
49 return;
50 }
51
52 ffStrbufAppendF(&terminalFont->error, "find profile `%s` bookmark failed", profile);
53}
54
55static void detectAppleTerminal(FFTerminalFontResult* terminalFont)
56{
57 FF_STRBUF_AUTO_DESTROY font = ffStrbufCreate();
58 ffOsascript("tell application \"Terminal\" to font name of window frontmost & \" \" & font size of window frontmost", &font);
59
60 if(font.length == 0)
61 {
62 ffStrbufAppendS(&terminalFont->error, "executing osascript failed");
63 return;
64 }
65
66 ffFontInitWithSpace(&terminalFont->font, font.chars);
67}
68
69static void detectWarpTerminal(FFTerminalFontResult* terminalFont)
70{
71 NSError* error;
72 NSString* fileName = [NSString stringWithFormat:@"file://%s/Library/Preferences/dev.warp.Warp-Stable.plist", instance.state.platform.homeDir.chars];
73 NSDictionary* dict = [NSDictionary dictionaryWithContentsOfURL:[NSURL URLWithString:fileName]
74 error:&error];
75 if(error)
76 {
77 ffStrbufAppendS(&terminalFont->error, error.localizedDescription.UTF8String);
78 return;
79 }
80
81 NSString* fontName = dict[@"FontName"];
82 if(!fontName)
83 fontName = @"Hack";
84 else
85 fontName = [fontName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]];
86
87 NSString* fontSize = dict[@"FontSize"];
88 if(!fontSize)
89 fontSize = @"13";
90
91 ffFontInitValues(&terminalFont->font, fontName.UTF8String, fontSize.UTF8String);
92}
93
94bool ffDetectTerminalFontPlatform(const FFTerminalResult* terminal, FFTerminalFontResult* terminalFont)
95{
96 if(ffStrbufIgnCaseEqualS(&terminal->processName, "iterm.app") ||
97 ffStrbufStartsWithIgnCaseS(&terminal->processName, "iTermServer-"))
98 detectIterm2(terminalFont);
99 else if(ffStrbufIgnCaseEqualS(&terminal->processName, "Apple_Terminal"))
100 detectAppleTerminal(terminalFont);
101 else if(ffStrbufIgnCaseEqualS(&terminal->processName, "WarpTerminal"))
102 detectWarpTerminal(terminalFont);
103 else
104 return false;
105 return true;
106}