A native macOS desktop widget that displays common Neovim shortcuts. Click the widget to expand into a full searchable cheatsheet.
- Compact Widget - Floats on desktop showing 7 most common shortcuts
- Expanded Cheatsheet - Full window with 15 sections of keymaps (including Vim Basics for beginners)
- Menu Bar Icon - Quick access from top menu bar (
⌘icon) - Search - Filter keymaps by keystroke or description
- Collapsible Sections - Click headers to expand/collapse
- Desktop Accessory - Doesn't show in Dock, stays on all spaces
- macOS 14.0+
- Xcode 15.0+
cd /Users/dvz/Luckgrid/Code/Native/NvimCheatsheetWidget
xcodebuild -project NvimCheatsheetWidget.xcodeproj -scheme NvimCheatsheetWidget -configuration Release buildThe built app will be in:
~/Library/Developer/Xcode/DerivedData/NvimCheatsheetWidget-*/Build/Products/Release/NvimCheatsheetWidget.app
open NvimCheatsheetWidget.xcodeproj# Build and run
open ~/Library/Developer/Xcode/DerivedData/NvimCheatsheetWidget-*/Build/Products/Release/NvimCheatsheetWidget.appAdd this to your ~/.config/nvim/init.lua to open the widget when Neovim starts:
-- Auto-open NvimCheatsheetWidget on startup
vim.api.nvim_create_autocmd("VimEnter", {
callback = function()
local app_path = vim.fn.expand("~/Library/Developer/Xcode/DerivedData/NvimCheatsheetWidget-*/Build/Products/Release/NvimCheatsheetWidget.app")
local expanded_path = vim.fn.glob(app_path)
if expanded_path ~= "" then
vim.fn.jobstart({ "open", expanded_path }, { detach = true })
end
end,
})Add this to your ~/.config/nvim/init.lua to open/focus the widget with <Space>?:
-- Open NvimCheatsheetWidget if not already running
vim.keymap.set("n", "<leader>?", function()
local app_path = vim.fn.expand("~/Library/Developer/Xcode/DerivedData/NvimCheatsheetWidget-*/Build/Products/Release/NvimCheatsheetWidget.app")
local expanded_path = vim.fn.glob(app_path)
if expanded_path == "" then
vim.notify("NvimCheatsheetWidget not found. Build it first.", vim.log.levels.WARN)
return
end
-- Open/focus the app
vim.fn.jobstart({ "open", expanded_path }, { detach = true })
end, { desc = "Open cheatsheet widget" })- The widget appears in the bottom-right corner of your screen
- Drag the widget to reposition it anywhere on screen
- Click the close button (X) to hide the widget
- Click the expand button to open the full cheatsheet
- Use the search bar to filter keymaps
- Click section headers to collapse/expand sections
- Menu bar icon (
⌘) provides quick access:- Open Cheatsheet (
⌘C) - Show Widget (
⌘W) - Quit (
⌘Q)
- Open Cheatsheet (
Edit NvimCheatsheetWidget/Keymaps.swift to modify the shortcuts:
compactKeymaps- Array of keymaps shown in the compact widgetkeymapSections- Array of sections for the expanded cheatsheet
Each keymap has:
Keymap(keys: "<Space>ff", description: "Find files")Each section has:
KeymapSection(title: "Navigation", icon: "arrow.up.arrow.down", keymaps: [...])Icons use SF Symbols names (e.g., "folder", "magnifyingglass", "terminal").
The app uses SF Symbols throughout. You can change icons in two places:
Edit NvimCheatsheetWidgetApp.swift:
button.image = NSImage(systemSymbolName: "command", accessibilityDescription: "Neovim Cheatsheet")Edit WidgetView.swift:
Image(systemName: "command")| Symbol | Description |
|---|---|
"command" |
⌘ Command key (current) |
"terminal" |
Terminal icon |
"terminal.fill" |
Filled terminal |
"keyboard" |
Keyboard icon |
"book" |
Book outline |
"book.fill" |
Filled book |
"chevron.left.forwardslash.chevron.right" |
</> code brackets |
"questionmark.circle" |
Help icon |
"doc.text" |
Document with text |
Browse all SF Symbols using Apple's SF Symbols app.
To use your own icon image instead of SF Symbols:
- Add a 16x16 or 18x18 PNG to the project (drag into Xcode)
- Update the code:
// Menu bar custom image
if let button = statusItem?.button {
button.image = NSImage(named: "myCustomIcon")
}
// Widget custom image
Image("myCustomIcon")
.resizable()
.frame(width: 16, height: 16)NvimCheatsheetWidget/ # Root project folder (PascalCase)
├── NvimCheatsheetWidget.xcodeproj/ # Xcode project bundle
│ └── project.pbxproj # Project configuration
├── README.md
└── NvimCheatsheetWidget/ # Source group (matches target name)
├── NvimCheatsheetWidgetApp.swift # App entry point & window management
├── WidgetView.swift # Compact widget UI
├── CheatsheetView.swift # Expanded cheatsheet UI
├── Keymaps.swift # All keymap definitions
└── Info.plist # App configuration
This follows Xcode's default structure where the root folder and inner source group share the same name:
| Element | Convention | Example |
|---|---|---|
| Root folder | PascalCase | NvimCheatsheetWidget/ |
| Xcode project | PascalCase | NvimCheatsheetWidget.xcodeproj |
| Source group | PascalCase (matches target) | NvimCheatsheetWidget/ |
| Swift files | PascalCase | WidgetView.swift |
| Bundle ID | reverse-domain.lowercase | com.luckgrid.NvimCheatsheetWidget |
The "duplication" of folder names is intentional:
- Outer folder - Directory on disk containing the project
- Inner folder - Xcode group representing the app target
- Swift Documentation - Official Swift language guide
- SwiftUI Tutorials - Apple's official SwiftUI tutorials
- Hacking with Swift - Free Swift/SwiftUI tutorials
- Swift by Sundell - Swift articles and podcasts
- macOS App Development - Apple's macOS dev resources
- AppKit Documentation - Native macOS UI framework
- NSWindow Programming Guide - Window management
- About the macOS App Architecture
- Status Items - Menu bar icons (NSStatusItem)
- Desktop Accessories - Apps that hide from Dock
- Floating Windows - Window layering
- SF Symbols - Apple's icon library (5,000+ symbols)
- Human Interface Guidelines - macOS design patterns
- Apple Design Resources - Templates and assets
MIT



