Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
82 changes: 82 additions & 0 deletions packages/browser-renderer/src/__tests__/fontSync.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/** @jest-environment node */

import puppeteer from 'puppeteer';
import { PORT } from 'config/jest/testServer';

import type { Browser, Page } from 'puppeteer';

const setup = async (browser: Browser): Promise<Page> => {
const page = await browser.newPage();
await page.setViewport({ width: 300, height: 200, deviceScaleFactor: 2 });
await page.goto(`http://localhost:${PORT}`);
await page.waitForSelector('input');
return page;
};

const run = async (page: Page, cmd: string) => {
await page.keyboard.type(`:${cmd}`);
await page.keyboard.press('Enter');
};

describe('Font sync between VVset fontfamily and &guifont', () => {
jest.setTimeout(30000);

let browser: Browser;
let page: Page;

beforeAll(async () => {
browser = await puppeteer.launch({
headless: true,
slowMo: 10,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
});

afterAll(async () => {
// await browser.close();
});

beforeEach(async () => {
page = await setup(browser);
});

afterEach(async () => {
await page.close();
});

test('VVset fontfamily renders with the requested font', async () => {
await run(page, 'VVset fontfamily=Monaco');
await run(page, 'VVset fontsize=14');
await page.keyboard.type('iHello Monaco');
await page.keyboard.press('Escape');
const image = await page.screenshot();
expect(image).toMatchImageSnapshot();
});

test('set guifont=<family> syncs to VV fontfamily', async () => {
await run(page, 'set guifont=Menlo');
await run(page, 'VVset fontsize=14');
await page.keyboard.type('iguifont Menlo');
await page.keyboard.press('Escape');
const image = await page.screenshot();
expect(image).toMatchImageSnapshot();
});

test('set guifont=<family>:h<size> syncs both family and size', async () => {
await run(page, 'set guifont=Courier\\ New:h16');
await page.keyboard.type('iCourier h16');
await page.keyboard.press('Escape');
const image = await page.screenshot();
expect(image).toMatchImageSnapshot();
});

test('VVset fontfamily updates &guifont (reverse sync)', async () => {
await run(page, 'VVset fontfamily=Monaco');
await run(page, 'VVset fontsize=15');
// `:set guifont?` echoes the value to the command line, which the
// screenshot captures.
await run(page, 'set guifont?');
const image = await page.screenshot();
expect(image).toMatchImageSnapshot();
});
});
24 changes: 2 additions & 22 deletions packages/browser-renderer/src/screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -443,18 +443,6 @@ const screen = ({
cursorEl.style.transform = `translate(${left}px, ${top}px)`;
};

const optionSet = {
guifont: (newFont: string) => {
const [newFontFamily, newFontSize] = newFont.trim().split(':h');
if (newFontFamily && newFontFamily !== '') {
nvim.command(`VVset fontfamily=${newFontFamily.replace(/_/g, '\\ ')}`);
if (newFontSize && newFontFamily !== '') {
nvim.command(`VVset fontsize=${newFontSize}`);
}
}
},
};

const recalculateHighlightTable = () => {
(Object.keys(highlightTable) as unknown as number[]).forEach((id) => {
if (id > 0) {
Expand Down Expand Up @@ -573,16 +561,8 @@ const screen = ({
modeInfoSet = props[0][1].reduce((r, modeInfo) => ({ ...r, [modeInfo.name]: modeInfo }), {});
},

option_set: (options) => {
options.forEach(([option, value]) => {
// @ts-expect-error TODO
if (optionSet[option]) {
// @ts-expect-error TODO
optionSet[option](value);
} else {
// console.warn('Unknown option', option, value); // eslint-disable-line no-console
}
});
option_set: () => {
/* empty */
},

mode_change: (modes) => {
Expand Down
49 changes: 49 additions & 0 deletions packages/electron/bin/vvset.vim
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,52 @@ let g:vv_default_settings = {

let g:vv_settings = deepcopy(g:vv_default_settings)

" Guard against infinite recursion when syncing fontfamily/fontsize and &guifont.
let g:vv_syncing_font = 0

" Apply VV's current fontfamily + fontsize to nvim's &guifont.
" Builds "<family-1>:h<size>,<family-2>,..." so :set guifont? matches VV.
function! s:SyncGuifont()
if g:vv_syncing_font | return | endif
let l:parts = split(get(g:vv_settings, 'fontfamily', ''), ',')
if empty(l:parts) | return | endif
let l:size = get(g:vv_settings, 'fontsize', '')
let l:first = escape(l:parts[0], ' \')
if l:size !=# '' && l:size != 0
let l:first .= ':h' . l:size
endif
let l:rest = map(l:parts[1:], 'escape(v:val, " \\")')
let l:guifont = empty(l:rest) ? l:first : l:first . ',' . join(l:rest, ',')
let g:vv_syncing_font = 1
try
execute 'set guifont=' . l:guifont
catch
endtry
let g:vv_syncing_font = 0
endfunction

" Parse &guifont and apply its first entry's family + :h<size> to VV.
function! s:SyncFromGuifont(value)
if g:vv_syncing_font || a:value ==# '' | return | endif
let l:first = split(a:value, ',')[0]
let l:family = substitute(l:first, ':h.*$', '', '')
if l:family ==# '' | return | endif
let l:size = matchstr(l:first, ':h\zs[0-9.]\+')
let g:vv_syncing_font = 1
call VVsetItem('fontfamily=' . l:family)
if l:size !=# ''
call VVsetItem('fontsize=' . l:size)
endif
let g:vv_syncing_font = 0
endfunction

augroup VVFontSync
autocmd!
autocmd OptionSet guifont call s:SyncFromGuifont(v:option_new)
" Catch &guifont set in init.vim — OptionSet does not fire during startup.
autocmd VimEnter * call s:SyncFromGuifont(&guifont)
augroup END

" Custom VVset command, mimic default set command (:help set) with
" settings specified in g:vv_default_settings
function! VVset(...)
Expand Down Expand Up @@ -124,6 +170,9 @@ function! VVsetItem(name)
if has_key(g:vv_settings, l:name)
let g:vv_settings[l:name] = l:value
call rpcnotify(get(g:, "vv_channel", 1), "vv:set", l:name, l:value)
if l:name ==# 'fontfamily' || l:name ==# 'fontsize'
call s:SyncGuifont()
endif
else
echoerr "Unknown option: ".l:name
endif
Expand Down
2 changes: 1 addition & 1 deletion packages/electron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@vvim/electron",
"description": "Neovim GUI Client",
"author": "Igor Gladkoborodov <igor.gladkoborodov@gmail.com>",
"version": "2.6.2",
"version": "2.6.3",
"private": true,
"keywords": [
"vim",
Expand Down
49 changes: 49 additions & 0 deletions packages/server/bin/vvset.vim
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,52 @@ let g:vv_default_settings = {

let g:vv_settings = deepcopy(g:vv_default_settings)

" Guard against infinite recursion when syncing fontfamily/fontsize and &guifont.
let g:vv_syncing_font = 0

" Apply VV's current fontfamily + fontsize to nvim's &guifont.
" Builds "<family-1>:h<size>,<family-2>,..." so :set guifont? matches VV.
function! s:SyncGuifont()
if g:vv_syncing_font | return | endif
let l:parts = split(get(g:vv_settings, 'fontfamily', ''), ',')
if empty(l:parts) | return | endif
let l:size = get(g:vv_settings, 'fontsize', '')
let l:first = escape(l:parts[0], ' \')
if l:size !=# '' && l:size != 0
let l:first .= ':h' . l:size
endif
let l:rest = map(l:parts[1:], 'escape(v:val, " \\")')
let l:guifont = empty(l:rest) ? l:first : l:first . ',' . join(l:rest, ',')
let g:vv_syncing_font = 1
try
execute 'set guifont=' . l:guifont
catch
endtry
let g:vv_syncing_font = 0
endfunction

" Parse &guifont and apply its first entry's family + :h<size> to VV.
function! s:SyncFromGuifont(value)
if g:vv_syncing_font || a:value ==# '' | return | endif
let l:first = split(a:value, ',')[0]
let l:family = substitute(l:first, ':h.*$', '', '')
if l:family ==# '' | return | endif
let l:size = matchstr(l:first, ':h\zs[0-9.]\+')
let g:vv_syncing_font = 1
call VVsetItem('fontfamily=' . l:family)
if l:size !=# ''
call VVsetItem('fontsize=' . l:size)
endif
let g:vv_syncing_font = 0
endfunction

augroup VVFontSync
autocmd!
autocmd OptionSet guifont call s:SyncFromGuifont(v:option_new)
" Catch &guifont set in init.vim — OptionSet does not fire during startup.
autocmd VimEnter * call s:SyncFromGuifont(&guifont)
augroup END

" Custom VVset command, mimic default set command (:help set) with
" settings specified in g:vv_default_settings
function! VVset(...)
Expand Down Expand Up @@ -124,6 +170,9 @@ function! VVsetItem(name)
if has_key(g:vv_settings, l:name)
let g:vv_settings[l:name] = l:value
call rpcnotify(get(g:, "vv_channel", 1), "vv:set", l:name, l:value)
if l:name ==# 'fontfamily' || l:name ==# 'fontsize'
call s:SyncGuifont()
endif
else
echoerr "Unknown option: ".l:name
endif
Expand Down
Loading