mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-11 15:37:29 +02:00
Merge pull request #1463 from ychin/guifont-system-monospace
Support native macOS monospace font (SF Mono)
This commit is contained in:
+15
-4
@@ -1129,11 +1129,22 @@ That's all. XLFDs are not used. For Chinese this is reported to work well: >
|
||||
<
|
||||
(Replace gui_gtk2 with gui_gtk3 for the GTK+ 3 GUI)
|
||||
|
||||
For Mac OSX you can use something like this: >
|
||||
:set guifont=Monaco:h10
|
||||
Also see 'macatsui', it can help fix display problems {not in MacVim}.
|
||||
In MacVim, fonts with spaces are set like this: >
|
||||
MacVim *macvim-guifont*
|
||||
|
||||
For MacVim you can use something like this: >
|
||||
:set guifont=Menlo:h10
|
||||
Fonts with spaces are set like this: >
|
||||
:set guifont=DejaVu\ Sans\ Mono:h13
|
||||
To use bold/italic fonts, use the fully specified PostScript name of the
|
||||
font, like so: >
|
||||
:set guifont=Menlo-Bold:h13
|
||||
To use the system native monospace font (which is SF Mono in new macOS
|
||||
versions), use the `-monospace-` keyword: >
|
||||
:set guifont=-monospace-:h12
|
||||
You can also specify the font weight of the native monospace font (refer to
|
||||
Apple documentation for `NSFontWeight` for possible values): >
|
||||
:set guifont=-monospace-Light:h11
|
||||
:set guifont=-monospace-Medium:h11
|
||||
<
|
||||
Mono-spaced fonts *E236*
|
||||
|
||||
|
||||
@@ -118,6 +118,9 @@ These are the non-standard options that MacVim supports:
|
||||
'fuoptions' 'macligatures' 'macmeta' 'macthinstrokes'
|
||||
'toolbariconsize' 'transparency'
|
||||
|
||||
These are GUI-related Vim options that have MacVim-specific behaviors:
|
||||
'guifont'
|
||||
|
||||
*macvim-commands*
|
||||
These are the non-standard commands that MacVim supports:
|
||||
|:macaction| |:macmenu|
|
||||
|
||||
@@ -8622,6 +8622,7 @@ macvim-encoding gui_mac.txt /*macvim-encoding*
|
||||
macvim-find gui_mac.txt /*macvim-find*
|
||||
macvim-full-screen gui_mac.txt /*macvim-full-screen*
|
||||
macvim-gestures gui_mac.txt /*macvim-gestures*
|
||||
macvim-guifont gui.txt /*macvim-guifont*
|
||||
macvim-help-menu gui_mac.txt /*macvim-help-menu*
|
||||
macvim-hints gui_mac.txt /*macvim-hints*
|
||||
macvim-internal-variables gui_mac.txt /*macvim-internal-variables*
|
||||
|
||||
@@ -87,6 +87,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
// NSFontChanging methods
|
||||
//
|
||||
- (void)changeFont:(nullable id)sender;
|
||||
- (NSFontPanelModeMask)validModesForFontPanel:(NSFontPanel *)fontPanel;
|
||||
|
||||
//
|
||||
// NSMenuItemValidation
|
||||
|
||||
@@ -1299,9 +1299,10 @@ static void grid_free(Grid *grid) {
|
||||
MMMinRows * cellSize.height + insetSize.height + bot);
|
||||
}
|
||||
|
||||
// Called when font panel selection has been made. Send the selected font to
|
||||
// MMBackend so it would set guifont which will send a message back to MacVim to
|
||||
// call MMWindowController::setFont.
|
||||
// Called when font panel selection has been made or when adjusting font size
|
||||
// using modifyFont/NSSizeUpFontAction. Send the selected font to MMBackend so
|
||||
// it would set guifont which will send a message back to MacVim to call
|
||||
// MMWindowController::setFont.
|
||||
- (void)changeFont:(id)sender
|
||||
{
|
||||
NSFont *newFont = [sender convertFont:font];
|
||||
@@ -1319,11 +1320,25 @@ static void grid_free(Grid *grid) {
|
||||
[data appendBytes:&len length:sizeof(unsigned)];
|
||||
[data appendBytes:[name UTF8String] length:len];
|
||||
|
||||
// We don't update guifontwide for now, as panel font selection
|
||||
// shouldn't affect them. This does mean Cmd +/- does not work for
|
||||
// them for now.
|
||||
const unsigned wideLen = 0;
|
||||
[data appendBytes:&wideLen length:sizeof(unsigned)];
|
||||
|
||||
[[self vimController] sendMessage:SetFontMsgID data:data];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSFontPanelModeMask)validModesForFontPanel:(NSFontPanel *)fontPanel
|
||||
{
|
||||
// Lets the user pick only the font face / size, as other properties as not
|
||||
// useful. Still enable text/document colors as these affect the preview.
|
||||
// Otherwise it could just be white text on white background in the preview.
|
||||
return NSFontPanelModesMaskStandardModes & (~NSFontPanelModeMaskAllEffects | NSFontPanelModeMaskTextColorEffect | NSFontPanelModeMaskDocumentColorEffect);
|
||||
}
|
||||
|
||||
/// Specifies whether the menu item should be enabled/disabled.
|
||||
- (BOOL)validateMenuItem:(NSMenuItem *)item
|
||||
{
|
||||
|
||||
@@ -900,7 +900,44 @@ static BOOL isUnsafeMessage(int msgid);
|
||||
NSString *name = [[NSString alloc]
|
||||
initWithBytes:(void*)bytes length:len
|
||||
encoding:NSUTF8StringEncoding];
|
||||
NSFont *font = [NSFont fontWithName:name size:size];
|
||||
NSFont *font = nil;
|
||||
if ([name hasPrefix:MMSystemFontAlias]) {
|
||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_15
|
||||
if (@available(macos 10.15, *)) {
|
||||
NSFontWeight fontWeight = NSFontWeightRegular;
|
||||
if (name.length > MMSystemFontAlias.length) {
|
||||
const NSRange cmpRange = NSMakeRange(MMSystemFontAlias.length, name.length - MMSystemFontAlias.length);
|
||||
if ([name compare:@"UltraLight" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightUltraLight;
|
||||
else if ([name compare:@"Thin" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightThin;
|
||||
else if ([name compare:@"Light" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightLight;
|
||||
else if ([name compare:@"Regular" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightRegular;
|
||||
else if ([name compare:@"Medium" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightMedium;
|
||||
else if ([name compare:@"Semibold" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightSemibold;
|
||||
else if ([name compare:@"Bold" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightBold;
|
||||
else if ([name compare:@"Heavy" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightHeavy;
|
||||
else if ([name compare:@"Black" options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame)
|
||||
fontWeight = NSFontWeightBlack;
|
||||
}
|
||||
font = [NSFont monospacedSystemFontOfSize:size weight:fontWeight];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Fallback to Menlo on older macOS versions that don't support the system monospace font API
|
||||
font = [NSFont fontWithName:@"Menlo-Regular" size:size];
|
||||
}
|
||||
}
|
||||
else {
|
||||
font = [NSFont fontWithName:name size:size];
|
||||
}
|
||||
if (!font) {
|
||||
// This should only happen if the system default font has changed
|
||||
// name since MacVim was compiled in which case we fall back on
|
||||
|
||||
+2
-1
@@ -433,7 +433,8 @@ enum {
|
||||
|
||||
extern NSString *VimFindPboardType;
|
||||
|
||||
|
||||
// Alias for system monospace font name
|
||||
extern NSString *MMSystemFontAlias;
|
||||
|
||||
|
||||
@interface NSString (MMExtras)
|
||||
|
||||
@@ -40,6 +40,8 @@ NSString *MMRendererKey = @"MMRenderer";
|
||||
// Vim find pasteboard type (string contains Vim regex patterns)
|
||||
NSString *VimFindPboardType = @"VimFindPboardType";
|
||||
|
||||
NSString *MMSystemFontAlias = @"-monospace-";
|
||||
|
||||
int ASLogLevel = MM_ASL_LEVEL_DEFAULT;
|
||||
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "Miscellaneous.h"
|
||||
#import "MMAppController.h"
|
||||
#import "MMApplication.h"
|
||||
@@ -425,4 +427,35 @@ do { \
|
||||
[self waitForVimClose];
|
||||
}
|
||||
|
||||
/// Test that using "-monospace-" for system default monospace font works.
|
||||
- (void) testGuifontSystemMonospace {
|
||||
MMAppController *app = MMAppController.sharedInstance;
|
||||
|
||||
[app openNewWindow:NewWindowClean activate:YES];
|
||||
[self waitForVimOpenAndMessages];
|
||||
|
||||
MMTextView *textView = [[[[app keyVimController] windowController] vimView] textView];
|
||||
XCTAssertEqualObjects(@"Menlo-Regular", [[textView font] fontName]);
|
||||
|
||||
[self sendStringToVim:@":set guifont=-monospace-\n" withMods:0];
|
||||
[self waitForEventHandlingAndVimProcess];
|
||||
XCTAssertEqualObjects([textView font], [NSFont monospacedSystemFontOfSize:11 weight:NSFontWeightRegular]);
|
||||
|
||||
[self sendStringToVim:@":set guifont=-monospace-Heavy:h12\n" withMods:0];
|
||||
[self waitForEventHandlingAndVimProcess];
|
||||
XCTAssertEqualObjects([textView font], [NSFont monospacedSystemFontOfSize:12 weight:NSFontWeightHeavy]);
|
||||
|
||||
[[[app keyVimController] windowController] fontSizeUp:nil];
|
||||
[self waitForEventHandlingAndVimProcess];
|
||||
XCTAssertEqualObjects([textView font], [NSFont monospacedSystemFontOfSize:13 weight:NSFontWeightHeavy]);
|
||||
|
||||
[[[app keyVimController] windowController] fontSizeDown:nil];
|
||||
[self waitForEventHandlingAndVimProcess];
|
||||
XCTAssertEqualObjects([textView font], [NSFont monospacedSystemFontOfSize:12 weight:NSFontWeightHeavy]);
|
||||
|
||||
// Clean up
|
||||
[[app keyVimController] sendMessage:VimShouldCloseMsgID data:nil];
|
||||
[self waitForVimClose];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -153,7 +153,8 @@ enum {
|
||||
|
||||
|
||||
@interface NSNumber (MMExtras)
|
||||
// HACK to allow font size to be changed via menu (bound to Cmd+/Cmd-)
|
||||
// Used by modifyFont:/convertFont: to allow font size to be changed via menu
|
||||
// (bound to Cmd+/Cmd-) or using macaction fontSizeUp:/fontSizeDown:.
|
||||
- (NSInteger)tag;
|
||||
@end
|
||||
|
||||
|
||||
+44
-2
@@ -32,11 +32,13 @@ static BOOL MMNoMRU = NO;
|
||||
|
||||
static NSString *MMDefaultFontName = @"Menlo-Regular";
|
||||
static int MMDefaultFontSize = 11;
|
||||
static char *MMDefaultFontStr = "Menlo-Regular:h11";
|
||||
static char *MMDefaultFontSizeStr = "h11";
|
||||
static int MMMinFontSize = 6;
|
||||
static int MMMaxFontSize = 100;
|
||||
|
||||
// This is duplicated in MMVimController. Could consolidate in the future.
|
||||
static NSString *(system_font_weights[]) = { @"UltraLight", @"Thin", @"Light", @"Regular", @"Medium", @"Semibold", @"Bold", @"Heavy", @"Black" };
|
||||
|
||||
static BOOL MMShareFindPboard = YES;
|
||||
|
||||
static GuiFont gui_macvim_font_with_name(char_u *name);
|
||||
@@ -1141,6 +1143,22 @@ gui_macvim_font_with_name(char_u *name)
|
||||
componentsJoinedByString:@" "];
|
||||
}
|
||||
|
||||
const BOOL isSystemFont = [fontName hasPrefix:MMSystemFontAlias];
|
||||
if (isSystemFont) {
|
||||
if (fontName.length > MMSystemFontAlias.length) {
|
||||
BOOL invalidWeight = YES;
|
||||
const NSRange cmpRange = NSMakeRange(MMSystemFontAlias.length, fontName.length - MMSystemFontAlias.length);
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(system_font_weights); i++) {
|
||||
if ([fontName compare:system_font_weights[i] options:NSCaseInsensitiveSearch range:cmpRange] == NSOrderedSame) {
|
||||
invalidWeight = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (invalidWeight)
|
||||
return NOFONT;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parseFailed && [fontName length] > 0) {
|
||||
if (size < MMMinFontSize) size = MMMinFontSize;
|
||||
if (size > MMMaxFontSize) size = MMMaxFontSize;
|
||||
@@ -1148,6 +1166,7 @@ gui_macvim_font_with_name(char_u *name)
|
||||
// If the default font is requested we don't need to check if NSFont
|
||||
// can load it. Otherwise we ask NSFont if it can load it.
|
||||
if ([fontName isEqualToString:MMDefaultFontName]
|
||||
|| isSystemFont
|
||||
|| [NSFont fontWithName:fontName size:size])
|
||||
return [[NSString alloc] initWithFormat:@"%@:h%d", fontName, size];
|
||||
}
|
||||
@@ -1170,7 +1189,9 @@ gui_mch_expand_font(optexpand_T *args, void *param, int (*add_match)(char_u *val
|
||||
{
|
||||
// If guifont is empty, and we want to fill in the orig value, suggest
|
||||
// the default so the user can modify it.
|
||||
if (add_match((char_u *)MMDefaultFontStr) != OK)
|
||||
NSString *defaultFontStr = [NSString stringWithFormat:@"%@:h%d",
|
||||
MMDefaultFontName, MMDefaultFontSize];
|
||||
if (add_match((char_u *)[defaultFontStr UTF8String]) != OK)
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1185,6 +1206,27 @@ gui_mch_expand_font(optexpand_T *args, void *param, int (*add_match)(char_u *val
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wide) {
|
||||
// Add system-native monospace font alias to completion.
|
||||
char buf[40];
|
||||
[MMSystemFontAlias getCString:buf maxLength:ARRAY_LENGTH(buf) encoding:NSASCIIStringEncoding];
|
||||
if (add_match((char_u*)buf) != OK)
|
||||
return;
|
||||
const size_t fontAliasLen = STRLEN(buf);
|
||||
if (STRNCMP(xp->xp_pattern, buf, fontAliasLen) == 0) {
|
||||
// We additionally complete with font weights like "bold". We only
|
||||
// do so if starting with "-monospace-" already to avoid spamming
|
||||
// the user with too many variations on this.
|
||||
for (size_t i = 0; i < ARRAY_LENGTH(system_font_weights); i++) {
|
||||
[system_font_weights[i] getCString:buf+fontAliasLen
|
||||
maxLength:ARRAY_LENGTH(buf)-fontAliasLen
|
||||
encoding:NSASCIIStringEncoding];
|
||||
if (add_match((char_u*)buf) != OK)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NSFontManager *fontManager = [NSFontManager sharedFontManager];
|
||||
NSArray<NSString *> *availableFonts;
|
||||
if (wide)
|
||||
|
||||
@@ -433,6 +433,28 @@ func Test_set_guifont()
|
||||
let &guifont = guifont_saved
|
||||
endfunc
|
||||
|
||||
func Test_set_guifont_macvim()
|
||||
CheckFeature gui_macvim
|
||||
let guifont_saved = &guifont
|
||||
let guifontwide_saved = &guifontwide
|
||||
|
||||
set guifont=-monospace-
|
||||
call assert_equal('-monospace-:h11', getfontname())
|
||||
set guifont=-monospace-Semibold
|
||||
call assert_equal('-monospace-Semibold:h11', getfontname())
|
||||
|
||||
call assert_fails('set guifont=-monospace-SemiboldInvalidWeight', 'E596')
|
||||
|
||||
set guifont=Menlo\ Regular
|
||||
call assert_equal('Menlo Regular:h11', getfontname())
|
||||
|
||||
set guifont=
|
||||
call assert_equal('Menlo-Regular:h11', getfontname())
|
||||
|
||||
let &guifontwide = guifontwide_saved
|
||||
let &guifont = guifont_saved
|
||||
endfunc
|
||||
|
||||
func Test_set_guifontset()
|
||||
CheckFeature xfontset
|
||||
let skipped = ''
|
||||
@@ -641,6 +663,13 @@ func Test_expand_guifont()
|
||||
call assert_equal(['Menlo-Regular'], getcompletion('set guifont=Menl*lar$', 'cmdline'))
|
||||
call assert_equal(['Menlo-Regular'], getcompletion('set guifontwide=Menl*lar$', 'cmdline'))
|
||||
|
||||
" Test system monospace font option. It's always the first option after
|
||||
" the existing font.
|
||||
call assert_equal('-monospace-', getcompletion('set guifont=', 'cmdline')[1])
|
||||
call assert_equal('-monospace-', getcompletion('set guifont=-monospace-', 'cmdline')[0])
|
||||
call assert_equal('-monospace-UltraLight', getcompletion('set guifont=-monospace-', 'cmdline')[1])
|
||||
call assert_equal(['-monospace-Medium'], getcompletion('set guifont=-monospace-Med', 'cmdline'))
|
||||
|
||||
" Make sure non-monospace fonts are filtered out only in 'guifont'
|
||||
call assert_equal([], getcompletion('set guifont=Hel*tica$', 'cmdline'))
|
||||
call assert_equal(['Helvetica'], getcompletion('set guifontwide=Hel*tica$', 'cmdline'))
|
||||
|
||||
Reference in New Issue
Block a user