Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
24 changes: 10 additions & 14 deletions colors/tools/sample_messages.vim
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
" Usage:
" $ vim -Nu NONE -S colors/tools/sample_messages.vim +source\ colors/blue.vim
function! Echoes()
echohl ErrorMsg
echo 'ErrorMsg'
echohl ModeMsg
echo 'ModeMsg'
echohl MoreMsg
echo 'MoreMsg'
echohl Question
echo 'Question'
echohl WarningMsg
echo 'WarningMsg'
echohl None
endfunction
call feedkeys(':call Echoes()')
Comment on lines -4 to -16

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This did not play well with screen dumps, because the code that starts Vim in a terminal window needs to checks that the screen has been drawn and for that it relies on the presence of the ruler. That's why I have rewritten this as below.

setlocal bufhidden=wipe buftype=nofile nobuflisted noswapfile
botright vnew

let s:higroups = ['ErrorMsg', 'ModeMsg', 'MoreMsg', 'Question', 'WarningMsg']

for higroup in s:higroups
call matchadd(higroup, higroup)
endfor

call setline(1, s:higroups)
114 changes: 114 additions & 0 deletions colors/tools/screendump.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
vim9script

import './term_util.vim' as util

const SCRIPT_DIR = fnamemodify(resolve(expand('<sfile>:p')), ':h')
const COLORSCHEMES_DIR = fnamemodify(SCRIPT_DIR, ':h')
const SELFIE_DURATION = 500 # How much time (in ms) to wait for pending
Comment thread
lifepillar marked this conversation as resolved.
Outdated
# updates. A lower value makes screen dumps
# faster to obtain, but they may not be accurate.

var busy = false

def TakeSelfie(
colorscheme: string, # Path to a color scheme
script: string, # Path to a script setting up the desired screen state
outfile: string, # Dump file
opts: dict<any> = {} # See RunInVimTerminal()
)
# Make sure the window is full width
execute "normal" "\<c-w>o"

var buf = util.RunVimInTerminal(script, colorscheme, opts)

# Redraw to execute the code that updates the screen. Otherwise we get the
# text and attributes only from the internal buffer.
redraw

# The timer allows Vim running inside the terminal to continue updating.
# This is necessary to take reliable screenshots for some scripts, such as
# sample_terminal.vim.
timer_start(SELFIE_DURATION, (t) => {
term_dumpwrite(buf, outfile)
util.StopVimInTerminal(buf)
busy = false
})
enddef

# Take screen dumps of a set of color schemes.
# If `background` is not empty, set background to the given value when
# starting Vim. `opts` is a dictionary with possible keys:
#
# "outdir" - The output directory (default: './dumps')
# "envs" - A list of t_Co values to use. The default for terminal Vim
# is [256, 16, 8, 0], for GUI is [-1].
# "scripts" - A list of paths of scripts to use. By default all `sample*.vim` scripts
# are used.
# "colorschemes" - A list of paths of color schemes to use. By default, all
# color schemes are used.
export def TakeSelfies(
background: string,
opts: dict<any> = {}
)
var outdir: string = get(opts, 'outdir', 'dumps')
var envs: list<number> = get(opts, 'envs', has('gui_running') ? [-1] : get(opts, 'envs', [256, 16, 8, 0]))
var scripts: list<string> = get(opts, 'scripts', glob($'{SCRIPT_DIR}/sample*.vim', 0, 1))
var colorschemes: list<string> = get(opts, 'colorschemes', glob($'{COLORSCHEMES_DIR}/*.vim', 0, 1))

var t_Co_saved = &t_Co

mkdir(outdir, 'p')

for colorscheme in colorschemes
var name = fnamemodify(colorscheme, ":t:r")

for script in scripts
for t_Co in envs
var scriptname = fnamemodify(script, ":t:r")
var affix = t_Co >= 0 ? $'-{scriptname}-{t_Co}' : $'-{scriptname}-gui'
var outfile = $"{outdir}/{name .. affix .. '.dump'}"

# Poll for timer until it is expired
while busy
sleep 1m
endwhile

busy = true

if t_Co >= 0
execute $'set t_Co={t_Co}'
endif

TakeSelfie(
colorscheme,
script,
outfile,
{background: background}
)
endfor
endfor
endfor

# Wait for the last selfie to complete
while busy
sleep 1m
endwhile

execute $'set t_Co={t_Co_saved}'
enddef

# Examples:
#
# TakeSelfies('dark', {colorschemes: glob('../*.vim', 0, 1)})
# TakeSelfies('light', {
# colorschemes: ['../lunaperche.vim', '../quiet.vim', '../retrobox.vim', '../wildcharm.vim'],
# scripts: ['sample_messages.vim', 'sample_terminal.vim'],
# envs: [256, 0],
# })
#
# TakeSelfie(
# '../lunaperche.vim',
# './sample_terminal.vim',
# 'lunaperche_light_sample_terminal.dump',
# {background: 'light'}
# )
131 changes: 131 additions & 0 deletions colors/tools/term_util.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
vim9script

# Wait for F() to return true.
# Adapted from WaitForCommon() in vim/src/testdir/term_util.vim.
# Return the waiting time for success, -1 for failure.
def WaitFor(F: func(): bool, timeout = 5000): number
var slept = 0
var start = reltime()

while true
if F()
return slept
endif

if slept >= timeout
break
endif

sleep 1m

slept = float2nr(reltimefloat(reltime(start)) * 1000)
endwhile

return -1 # timed out
enddef

# Run Vim with the given script and the given color scheme in a new terminal
# window. By default uses a window size of 20 lines and 75 columns.
# Returns the buffer number of the terminal.
#
# For example:
#
# RunVimInTerminal('./colors/tools/sample_diff.vim', './colors/blue.vim')
#
# Inspired by RunVimInTerminal() in vim/src/testdir/term_util.vim.
#
# `opts` is a dictionary with possible keys:
#
# "rows" - Height of the terminal window (default is 20)
# "cols" - Width of the terminal window (default is 75)
# "statusoff" - Number of lines the status is offset from default
# "background" - The background to set (default is «don't set»)
export def RunVimInTerminal(script: string, colorscheme: string, opts: dict<any> = {}): number
var rows: number = get(opts, 'rows', 20)
var cols: number = get(opts, 'cols', 75)
var statusoff: number = get(opts, 'statusoff', 1)
var background: string = get(opts, 'background', '')

if !filereadable(script)
throw $'File not found: {script}'
endif

if !filereadable(colorscheme)
throw $'File not found: {colorscheme}'
endif

# Make a horizontal and vertical split, so that we can get exactly the right
# size terminal window. Works only when the current window is full width.
if &columns != winwidth(0)
throw 'The current window is not full width'
endif

split
vsplit

var setbackground = empty(background) ? [] : ['-c', $'set bg={background}']
var vim = [
'vim', '-N', '-u', 'NONE',
'--cmd', 'set ruler', # Helps checking for screen drawing (see below)
] + setbackground + [
'-S', script,
$'+source {colorscheme}'
]
var options = {curwin: 1, term_rows: rows, term_cols: cols}
var buf = term_start(vim, options)

if &termwinsize == ''
# In the GUI we may end up with a different size, try to set it.
if term_getsize(buf) != [rows, cols]
term_setsize(buf, rows, cols)
endif

if term_getsize(buf) != [rows, cols]
throw $"Couldn't make the terminal the right size: got {term_getsize(buf)}, expected [{rows},{cols}]."
endif
endif

term_wait(buf, 10)

# Wait for "All" or "Top" of the ruler to be shown in the last line.
# That is, wait for the screen to be drawn completely.
var slept = WaitFor(
() => len(term_getline(buf, rows)) >= cols - 1 || len(term_getline(buf, rows - statusoff)) >= cols - 1
)

if slept < 0
throw 'Waiting for the terminal screen timed out'
endif

# Redraw to execute the code that updates the screen. Otherwise we get the
# text and attributes only from the internal buffer.
redraw

return buf
enddef

# Stop a Vim running in terminal buffer "buf".
# Adapted from StopVimInTerminal() from vim/src/testdir/term_util.vim.
export def StopVimInTerminal(buf: number, kill = true)
# Wait for all the pending updates to terminal to complete
term_wait(buf, 1)

# CTRL-O : works both in Normal mode and Insert mode to start a command line.
# In Command-line it's inserted, the CTRL-U removes it again.
term_sendkeys(buf, "\<C-O>:\<C-U>qa!\<CR>")

# Wait for all the pending updates to terminal to complete
term_wait(buf, 1)

# Wait up to five seconds for the terminal to end.
WaitFor(() => term_getstatus(buf) == "finished")

# If the buffer still exists forcefully wipe it.
if kill && bufexists(buf)
execute $':{buf}bwipe!'
endif
enddef

# Example:
#
# var b = RunVimInTerminal('./sample_terminal.vim', '../lunaperche.vim', {background: 'light'})