A Neovim plugin for creating and managing presenterm presentations with enhanced support for slide navigation, partials management, and live preview.
- Slide Management : Navigate, create, delete, reorder slides with ease using vim motions
- Partial Support : Include reusable content from partial files, useful when working with multiple presentations
- Interactive Reordering: Reorder slides interactively using vim line movements
- Code Execution : Toggle
presentermcode execution markers (+exec,+exec_replaceetc) - Execute Code Blocks : Run code blocks directly from Neovim
- Live Preview : Launch
presentermpreview in terminal with bi-directional sync - Bi-directional Sync : Navigate in markdown or presenterm, both stay synchronized
- Statistics : View presentation stats and time estimates
Note
lazy.nvim auto-detects rockspec files and will try to build via luarocks by default. Since this is a pure Lua plugin that doesn't require compilation, add build = false to skip the build step and avoid needing lua5.1/luajit.
Minimal setup (uses defaults):
{
"Piotr1215/presenterm.nvim",
build = false, -- Disable rockspec/luarocks build
opts = {}, -- Uses all defaults, auto-detects picker
}With optional picker (one of telescope/fzf-lua/snacks):
{
"Piotr1215/presenterm.nvim",
build = false,
dependencies = {
-- Choose one (or install separately):
"nvim-telescope/telescope.nvim", -- Option 1: Telescope
-- "ibhagwan/fzf-lua", -- Option 2: fzf-lua
-- "folke/snacks.nvim", -- Option 3: Snacks
},
opts = {},
}Custom setup with picker preference:
{
"Piotr1215/presenterm.nvim",
build = false,
config = function()
require("presenterm").setup({
default_keybindings = true,
picker = {
provider = "telescope", -- Options: "telescope", "fzf", "snacks", "builtin"
},
preview = {
command = "presenterm -xX",
presentation_preview_sync = true,
},
})
end,
}use "Piotr1215/presenterm.nvim"Note: This method may require lua5.1 or luajit installed on your system.
:Rocks install presenterm.nvimNote: This method requires lua5.1 or luajit installed on your system.
luarocks install presenterm.nvimThe plugin automatically detects presenterm presentations (by looking for slide markers like <!-- end_slide --> or frontmatter) and activates when you open a markdown file. You can also manually activate with :Presenterm activate.
Option 1: Use defaults (recommended)
require("presenterm").setup({
default_keybindings = true,
})Option 2: Customize with on_attach
require("presenterm").setup({
on_attach = function(bufnr)
vim.keymap.set("n", "]s", require("presenterm").next_slide, { buffer = bufnr, desc = "Next slide" })
vim.keymap.set("n", "[s", require("presenterm").previous_slide, { buffer = bufnr, desc = "Previous slide" })
end,
})Option 3: Map commands manually
vim.keymap.set("n", "]s", ":Presenterm next<cr>")
vim.keymap.set("n", "[s", ":Presenterm prev<cr>")
-- Note: Use the new :Presenterm command pattern shown below in Commands sectionDefault keymaps (when default_keybindings = true)
]s/[s- Next/previous slide<leader>sn- New slide<leader>ss- Split slide<leader>sd- Delete slide<leader>sy- Yank slide<leader>sv- Select slide<leader>sk/<leader>sj- Move slide up/down<leader>sR- Reorder slides<leader>sl- List slides<leader>sL- Select layout<leader>sp- Include partial<C-e>- Toggle +exec<leader>sr- Run code block<leader>sP- Preview presentation<leader>sc- Presentation stats
All commands use the :Presenterm <command> pattern for a clean namespace.
:Presenterm next- Go to next slide:Presenterm prev- Go to previous slide:Presenterm goto N- Go to slide N:Presenterm list- List all slides
:Presenterm new- Create new slide after current:Presenterm split- Split slide at cursor position:Presenterm delete- Delete current slide:Presenterm yank- Yank current slide:Presenterm select- Visually select current slide:Presenterm move-up- Move slide up:Presenterm move-down- Move slide down:Presenterm reorder- Interactive slide reordering
:Presenterm partial include- Include partial file:Presenterm partial edit- Edit partial file:Presenterm partial list- List all partials
:Presenterm exec toggle- Toggle code execution flags (plain → +exec → +exec_replace → +exec +acquire_terminal):Presenterm exec run- Run current code block
:Presenterm layout- Open picker to select and insert column layout templates
Available templates:
- Two Column layouts: 50/50, 60/40, 70/30
- Three Column layouts: 33/33/33, 50/25/25
- Sidebar layouts: 25/75 (left), 75/25 (right)
- Centered content: 20/60/20
Inserts full scaffolding with <!-- column_layout: [x, y] -->, column markers, and <!-- reset_layout -->.
:Presenterm preview- Preview presentation in terminal split:Presenterm stats- Show presentation statistics:Presenterm toggle-sync- Toggle bi-directional sync (navigate in markdown → presenterm follows, and vice versa)
:Presenterm activate- Manually activate presenterm mode:Presenterm deactivate- Deactivate presenterm mode for current buffer:Presenterm help- Show help
When presentation_preview_sync = true, navigation is synchronized bi-directionally:
Buffer → Terminal: Navigate in markdown with any motion (j, k, gg, G, /, etc.) → presenterm jumps to that slide
Terminal → Presenterm: Navigate in presenterm (n, p, <number>G) → markdown buffer cursor moves to that slide
Requirements:
- Presenterm footer must show slide count (e.g., "1 / 10")
- Works automatically with/without frontmatter (adjusts slide numbering)
- Sync prevents loops with 100ms debounce
Does NOT work when:
- Presenterm footer is customized to hide slide numbers
- Using custom footer configuration without "N / M" pattern
Auto-detects available pickers (Telescope/fzf-lua/Snacks) or falls back to vim.ui.select
The slide picker shows all slides with titles extracted from the content, including from partial files. Slides containing partials are marked with [P] indicator.
<CR>- Jump to selected slide<C-e>- Edit the first partial in the selected slide (if it contains any)
The partial picker has two modes:
-
Include mode (
:Presenterm partial include):<CR>- Insert include directive<C-e>- Edit the partial file
-
Edit mode (
:Presenterm partial edit):<CR>- Edit the partial file<C-i>- Insert include directive
You can add slide information to your statusline:
-- For lualine
sections = {
lualine_x = {
function()
return require("presenterm").slide_status()
end,
},
}{
slide_marker = "<!-- end_slide -->",
partials = {
directory = "_partials",
resolve_relative = true,
},
preview = {
command = "presenterm", -- Safe: commands won't execute
presentation_preview_sync = false,
login_shell = true, -- Loads PATH, env vars, etc.
},
picker = {
provider = nil, -- Auto-detect: telescope > fzf > snacks > builtin
},
on_attach = nil,
default_keybindings = false,
}By default:
- Commands in slides display but don't execute (safe for untrusted presentations)
- Shell environment loaded (PATH, nvm, pyenv, env vars available)
- No automatic keybindings (set
default_keybindings = trueor configure manually)
For presentations with live demos (docker, node, etc.):
preview = {
command = "presenterm -xX", -- Executes +exec code blocks
}Faster startup (skip environment loading):
preview = {
login_shell = false, -- ~200-500ms faster, but PATH, env vars unavailable
}A typical presenterm presentation structure:
project/
├── presentation.md # Main presentation file
└── _partials/ # Reusable content
├── intro.md
├── demo.md
└── conclusion.md
Example presentation.md:
---
title: My Presentation
author: Your Name
---
# Welcome
First slide content
<!-- end_slide -->
<!-- include: ../_partials/intro.md -->
<!-- end_slide -->
## Demo
```bash +exec
echo "This code can be executed"Run :checkhealth presenterm to diagnose common issues.
The health check will verify:
- Plugin is loaded and configured correctly
- presenterm CLI is installed and in PATH
- Picker plugins (telescope/fzf-lua/snacks) availability
- Partials directory configuration
- Preview and sync settings
Common issues:
-
Preview not working: Ensure presenterm CLI is installed:
cargo install presenterm # or check https://github.com/mfontanini/presenterm -
No picker UI: Install one of:
telescope.nvimfzf-luasnacks.nvim
-
Sync not working: Check that:
presentation_preview_sync = truein config- presenterm footer shows slide numbers (e.g., "1 / 10")
- Not using custom footer that hides slide numbers
MIT
