Vim Tips Wiki
Advertisement


Duplicate tip

This tip is very similar to the following:

These tips need to be merged – see the merge guidelines.

Tip 760 Printable Monobook Previous Next

created 2004 · complexity intermediate · author Wouter Bolsterlee · version 6.0


If you regularly switch to a larger or smaller font, for example because someone looking at your code thinks the letters are too small, or because you want to lay back in your chair while reading, this tip is for you.

The following script defines two commands, :LargerFont and :SmallerFont, to allow quick adjustments to the font size used in the gtk2 gui. Change minfontsize and maxfontsize to suit your needs. See below for alternative solutions.

To use this script, put the following code into ~/.vim/plugin/gtk2fontsize.vim or in your vimrc.

let s:pattern = '^\(.* \)\([1-9][0-9]*\)$'
let s:minfontsize = 6
let s:maxfontsize = 16
function! AdjustFontSize(amount)
  if has("gui_gtk2") && has("gui_running")
    let fontname = substitute(&guifont, s:pattern, '\1', '')
    let cursize = substitute(&guifont, s:pattern, '\2', '')
    let newsize = cursize + a:amount
    if (newsize >= s:minfontsize) && (newsize <= s:maxfontsize)
      let newfont = fontname . newsize
      let &guifont = newfont
    endif
  else
    echoerr "You need to run the GTK2 version of Vim to use this function."
  endif
endfunction

function! LargerFont()
  call AdjustFontSize(1)
endfunction
command! LargerFont call LargerFont()

function! SmallerFont()
  call AdjustFontSize(-1)
endfunction
command! SmallerFont call SmallerFont()

Related plugins[]

As an alternative, you could use one of these plugins which work with fonts on Unix and Windows systems:

  • quickfonts.vim : quickly switch between a list of favorite fonts, manage list of favorite fonts
  • guifont++.vim : Vim plugin for quickly changing GUI font size
  • fontsize : Vim plugin for adjusting GUI font size via "font size" mode single-key shortcuts

Mapping solution[]

Another alternative is to use the following mappings which use a clever substitute (no functions are required). This example works using gvim under Windows, where the command :set guifont? would show the font name and :h12 if the font size is 12 points, for example.

nnoremap <C-Up> :silent! let &guifont = substitute(
 \ &guifont,
 \ ':h\zs\d\+',
 \ '\=eval(submatch(0)+1)',
 \ '')<CR>
nnoremap <C-Down> :silent! let &guifont = substitute(
 \ &guifont,
 \ ':h\zs\d\+',
 \ '\=eval(submatch(0)-1)',
 \ '')<CR>
Explanation[]

For example, the command :echo &guifont might show Bitstream_Vera_Sans_Mono:h12:b:cANSI.

The substitute pattern :h\zs\d\+ looks for :h followed by a number (one or more digits). The \zs marks the start of what is found (so it skips the :h).

The replacement string \=eval(submatch(0)+1) uses:

\=
Following is an expression to be evaluated.
submatch(0)
The text that matched (this example finds 12 with \d\+).

eval()

Evaluate the following string (12+1).
Note[]

If you have multiple fonts listed, such as

:echo &guifont
Andale_Mono:h10,Menlo:h10,Consolas:h10

you can add 'g' to the last argument of the substitute command above to 'globally' replace all the font sizes.

nnoremap <C-Up> :silent! let &guifont = substitute(
 \ &guifont,
 \ ':h\zs\d\+',
 \ '\=eval(submatch(0)+1)',
 \ 'g')<CR>
nnoremap <C-Down> :silent! let &guifont = substitute(
 \ &guifont,
 \ ':h\zs\d\+',
 \ '\=eval(submatch(0)-1)',
 \ 'g')<CR>
Note[]

If you want to be able to use <C-+> and <C-->, this is currently not possible inside (g)vim as they don't map to a (unique) ascii-code (read more about it here https://groups.google.com/forum/#!topic/vim_dev/EZT_Q0YRmAM). If you're on windows, you can use AutoHotkey to circumvent this issue.

Create an autohotkey script (https://www.autohotkey.com/), and put the following inside it:

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

^+::
if WinActive("ahk_exe gvim.exe")
{
    Send, ^{Up}
}
return

^-::
if WinActive("ahk_exe gvim.exe")
{
    Send, ^{Down}
}
return

Name it something like vim.ahk, and put it inside this folder to have it be executed automatically on startup C:\Users\[User Name]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup.

References[]

Support for GTK3 and out-of-range cursize[]

Code below works with GTK3 (unfortunately I can't test against GTK2) as well as with cursize values outside of [s:minfontsize,s:maxfontsize].

function! AdjustFontSize(amount)
  if (has("gui_gtk2") || has("gui_gtk3"))  && has("gui_running")
    let fontname = substitute(&guifont, s:pattern, '\1', '')
    let cursize = substitute(&guifont, s:pattern, '\2', '')
    let newsize = cursize + a:amount
    if (newsize >= s:minfontsize) && (newsize <= s:maxfontsize)
      let newfont = fontname . newsize
      let &guifont = newfont
    endif
    if ((a:amount > 0) || (newsize >= s:minfontsize)) && ((a:amount < 0) || (newsize <= s:maxfontsize))
      let newfont = fontname . newsize
      let &guifont = newfont
    endif
  else
    echoerr "You need to run the GTK2 or GTK3 version of Vim to use this function."
  endif
endfunction

Multiplatform implementation[]

This version works in Linux, Windows, and macOS.

function! AdjustFontSize(amount)
    if !has("gui_running")
        return
    endif

    let l:min_font_size = 5
    let l:max_font_size = 64

    let l:font_info = GetFontInfo()
    if l:font_info.name == '' || l:font_info.size == ''
        return
    endif

    let l:font_name = l:font_info.name
    let l:font_size = l:font_info.size

    " Decrease font size.
    if a:amount == '-'
        let l:font_size = l:font_size - 1

    " Increase font size.
    elseif a:amount == '+'
        let l:font_size = l:font_size + 1

    " Use a specific font size.
    elseif str2nr(a:amount)
        let l:font_size = str2nr(a:amount)
    endif

    " Clamp font size.
    let l:font_size = max([l:min_font_size, min([l:max_font_size, l:font_size])])

    if matchstr(&guifont, ':') == '' " Linux guifont style.
        " \v           Very magical.
        " (\d+$)       Capture group:       Match [0-9] one-or-more times, at the end of the string.
        let l:font_size_pattern = '\v(\d+$)'
    else " Windows and macOS guifont style.
        " \v           Very magical.
        " (:h)@<=      Positive lookbehind: Match ':h'.
        " (\d+)        Capture group:       Match [0-9] one-or-more times.
        let l:font_size_pattern = '\v(:h)@<=(\d+)'
    endif

    " Update vim font size.
    let &guifont = substitute(&guifont, l:font_size_pattern, l:font_size, '')

    call DisplayFontInfo()
endfunction

function! DisplayFontSelector()
    if !has("gui_running")
        return
    endif

    " Display font selector.
    " NOTE: This only changes &guifont to '*' in terminal vim.
    set guifont=*

    " Display font info after font selector closes.
    call DisplayFontInfo()
endfunction

function! DisplayFontInfo()
    let l:font_info = GetFontInfo()
    if l:font_info.name == '' || l:font_info.size == ''
        return
    endif

    " Display font name and size.
    redraw | echomsg l:font_info.name . ' ' . l:font_info.size . '%'
endfunction

function! GetFontInfo()
    " Windows and macOS &guifont: Hack NF:h11:cANSI
    "                             3270Medium_NF:h10:W500:cANSI:qDRAFT
    " Linux &guifont: Hack Nerd Font Mono Regular 10

    if matchstr(&guifont, ':') == '' " Linux guifont style.
        " \v           Very magical.
        " (^.{-1,})    Capture group:       Anchored at the start of the string, match any character one-or-more times non-greedy.
        " ( \d+$)@=    Positive lookahead:  Match ' ' followed by [0-9] one-or-more times, at the end of the string.
        let l:font_name_pattern = '\v(^.{-1,})( \d+$)@='

        " \v           Very magical.
        " (\d+$)       Capture group:       Match [0-9] one-or-more times, at the end of the string.
        let l:font_size_pattern = '\v(\d+$)'
    else " Windows and macOS guifont style.
        " \v           Very magical.
        " (^.{-1,})    Capture group:       Anchored at the start of the string, match any character one-or-more times non-greedy.
        " (:)@=        Positive lookahead:  Match ':'.
        let l:font_name_pattern = '\v(^.{-1,})(:)@='

        " \v           Very magical.
        " (:h)@<=      Positive lookbehind: Match ':h'.
        " (\d+)        Capture group:       Match [0-9] one-or-more times.
        let l:font_size_pattern = '\v(:h)@<=(\d+)'
    endif

    let l:font_name = matchstr(&guifont, l:font_name_pattern)
    let l:font_size = matchstr(&guifont, l:font_size_pattern)

    return { 'name' : l:font_name, 'size' : l:font_size }
endfunction

" Bind Control + Mouse-wheel to zoom text.
" NOTE: Starting in version 9.0 this works in Windows. Previously it only worked in Linux and macOS. SEE: :h scroll-mouse-wheel
map <silent> <C-ScrollWheelDown> :call AdjustFontSize('-')<CR>
map <silent> <C-ScrollWheelUp> :call AdjustFontSize('+')<CR>

" Decrease font size.
nnoremap <silent> <F11> :call AdjustFontSize('-')<CR>
inoremap <silent> <F11> <Esc>:call AdjustFontSize('-')<CR>
vnoremap <silent> <F11> <Esc>:call AdjustFontSize('-')<CR>
cnoremap <silent> <F11> <Esc>:call AdjustFontSize('-')<CR>
onoremap <silent> <F11> <Esc>:call AdjustFontSize('-')<CR>

" Increase font size.
nnoremap <silent> <F12> :call AdjustFontSize('+')<CR>
inoremap <silent> <F12> <Esc>:call AdjustFontSize('+')<CR>
vnoremap <silent> <F12> <Esc>:call AdjustFontSize('+')<CR>
cnoremap <silent> <F12> <Esc>:call AdjustFontSize('+')<CR>
onoremap <silent> <F12> <Esc>:call AdjustFontSize('+')<CR>

" Set font size to my preferred size (10).
nnoremap <silent> <S-F11> :call AdjustFontSize(10)<CR>
inoremap <silent> <S-F11> <Esc>:call AdjustFontSize(10)<CR>
vnoremap <silent> <S-F11> <Esc>:call AdjustFontSize(10)<CR>
cnoremap <silent> <S-F11> <Esc>:call AdjustFontSize(10)<CR>
onoremap <silent> <S-F11> <Esc>:call AdjustFontSize(10)<CR>

" Display font selector.
nnoremap <silent> <S-F12> :call DisplayFontSelector()<CR>
inoremap <silent> <S-F12> <Esc>:call DisplayFontSelector()<CR>
vnoremap <silent> <S-F12> <Esc>:call DisplayFontSelector()<CR>
cnoremap <silent> <S-F12> <Esc>:call DisplayFontSelector()<CR>
onoremap <silent> <S-F12> <Esc>:call DisplayFontSelector()<CR>

Comments[]

Advertisement