Skip to content
GalvarcusPublic

About

Shared message logging mechanism for vim plugins written in vim9script.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

16 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Logger

Logger shows and logs the messages of Vim9 plugins. Each message names the plugin, script, and method that sent it. Logger can also write the messages of each plugin to its own log file.

Vim License: GPL v3

main: Generate Vimdoc Tests Development: Generate Vimdoc Tests

Contents

Requirements

Vim 9.1 or later. Logger does not load in Vim 9.0, in Neovim, or in compatible mode.

Installation

Install Logger together with each plugin that uses it.

With Vim packages:

git clone https://github.com/Galvarcus/Logger.git ~/.vim/pack/vendor/start/Logger

With vim-plug:

Plug 'Galvarcus/Logger'

Quick start

Import Logger at the top of a script, and make one Logger for the script:

vim9script

import 'Logger/logger.vim' as Log

var log = Log.Logger.new('MyPlugin', expand('<sfile>:t'))

def Save()
  log.Info('Saved.')
enddef

A call to Save() in foo.vim echoes this message:

MyPlugin - foo.vim - Save: Saved.

Usage

Logger objects

Log.Logger.new({plugin}, {script}, {level}) makes a Logger. All arguments are optional.

Argument Value
{plugin} Plugin name. Options for the plugin use this name.
{script} Script name, usually expand('<sfile>:t').
{level} Echo level for this Logger. Options can override it.

Make one Logger in each script. All Logger objects with the same plugin name use the same options and the same log file.

Methods

Method Effect
Info({msg}) Show an info message, as :echom does.
Warn({msg}) Show a warning with WarningMsg highlight.
Error({msg}) Show an error with ErrorMsg highlight.
Exception({exception}, {throwpoint}) Show a caught exception. The defaults are v:exception and v:throwpoint.
Fmt({msg}) Return an exception text to throw.
Try({Fn}) Call {Fn} and return its result. On an exception, show it and return v:none.

Each method also takes an optional last argument, {method}. When it is empty, Logger uses the name of the function that called it. A class method shows as Class.Method. Code at script level and code in a lambda have no method name.

Message format

An echoed message has this form:

MyPlugin - foo.vim - Save: [WARN] Disk almost full.

Logger omits an empty plugin, script, or method name. The tags are [WARN], [ERROR], and [EXCEPTION]. An info message has no tag. An exception also shows its throwpoint on a second line.

Exceptions

Catch an exception and show it:

try
  Risky()
catch
  log.Exception()
endtry

Try() does the same in one line:

var result = log.Try(() => Risky())

To throw where no try is near, use Fmt():

if exists('g:this')
  Use(g:this)
elseif exists('g:that')
  Use(g:that)
else
  throw log.Fmt('Neither this nor that.')
endif

Fmt() records and logs the message when you throw it. Vim shows an uncaught exception without Logger, so this puts it in the log file too. When a caller catches the text and calls Exception(), Logger shows the text once and does not record it again.

Levels

Level Messages
-1 None
0 Errors and exceptions
1 Warnings, errors, and exceptions
2 All

Startup messages

Logger holds messages sent before VimEnter and echoes them after Vim starts.1

Configuration

Each option has a global variable, g:logger_{option}, and a variable for each plugin, g:logger_{plugin}_{option}. {plugin} is the plugin name in lowercase, with each character other than a letter, digit, or underscore changed to _. For the plugin My-Plugin, it is my_plugin.

Logger uses the first value it finds:

  1. The plugin variable, such as g:logger_myplugin_level.
  2. The {level} argument of Logger.new(), for level only.
  3. The global variable, such as g:logger_level.
  4. The default.

Logger reads the options on each message, so a change applies at once. A value of the wrong type uses the default.

Option Default Effect
echo true Echo messages.
level 2 Echo level.
log_file false Write messages to a log file.
log_level 2 Log file level.
log_retention 10 Number of old log files to keep for each plugin. 0 keeps all.
log_dir '~/.Logger' Log file folder. Global only.

This example logs all plugins, keeps 20 old files for MyPlugin, and shows only its errors and warnings:

g:logger_log_file = true
g:logger_myplugin_log_retention = 20
g:logger_myplugin_level = 1

Log files

With log_file on, Logger writes the messages of each plugin to one file for each Vim session:

~/.Logger/myplugin_20260926_140311.log

Logger makes the folder and the file on the first message of the session. It then deletes the oldest files of that plugin until log_retention old files remain. The current file does not count.

Each message is one line. An exception adds its throwpoint on the next line:

2026-09-26 14:03:11 WARN MyPlugin - foo.vim - Save: Disk almost full.
2026-09-26 14:03:12 EXCEPTION MyPlugin - foo.vim - Load: No config file.
  at function <SNR>12_Load, line 3

When Logger cannot write the file, it shows one warning. That Logger then stops writing to the file until Vim restarts.

Commands

:LoggerMessages opens a scratch window with the last 200 messages of all plugins.

Development

Run the tests from the root of the repository:

vim -es -u NONE -N -c 'set rtp+=.' -c 'source tests/harness.vim' -c 'quit'
cat tests/results.txt

The Tests workflow runs the tests on the newest Vim and on Vim 9.1.0016. The Generate Vimdoc workflow makes doc/logger.txt from this file on each push to main and Development. Edit this file, not doc/logger.txt. You can also start both workflows by hand.

License

GNU General Public License 3.0. The full text is in LICENSE.

Footnotes

  1. Vim redraws the screen during startup, which hides earlier messages. ↩

About

Shared message logging mechanism for vim plugins written in vim9script.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages