Skip to content

Instantly share code, notes, and snippets.

@wojukasz
Last active April 6, 2025 15:44
Show Gist options
  • Save wojukasz/d76ca3162debc66d4227b9dc6049789e to your computer and use it in GitHub Desktop.
Save wojukasz/d76ca3162debc66d4227b9dc6049789e to your computer and use it in GitHub Desktop.
VsCode + Vim keybindings and settings - best of both worlds

Now stored in REPOSITORY - PLEASE USE IT GOING FORWARD

https://github.com/wojukasz/VimCode

VS Code Vim Configuration

Enhanced VS Code configuration with Vim keybindings for efficient coding workflows. This setup combines the power of Vim motions with VS Code's modern features.

Some of the shortcuts are experimental and I am trying things on the go so please leave a comment and feel free to adjust.

Features

💻 Editor Navigation

  • Vim-style split navigation (ctrl+h/j/k/l)
  • Quick file switching with alt+[ and alt+]
  • Efficient split management with alt+h/l for resizing

📁 File Explorer

  • Toggle sidebar: <leader>e
  • File navigation with Vim keys
  • Quick file operations (rename, create, delete)

🔍 Search and Replace

  • Enhanced workspace search with <leader>s w
  • Find in files: ctrl+shift+f
  • Navigate results: F4/Shift+F4

⚡ Quick Actions

  • Format document: ctrl+space f
  • Go to definition: ctrl+]
  • Navigate back: ctrl+t

🔧 Git Integration

  • Toggle blame: <leader>g b
  • Quick stage: <leader>g s
  • Pull: <leader>g p
  • Push: <leader>g P
  • View history: <leader>g h

🖥️ Terminal Integration

  • Toggle terminal: ctrl+;
  • Maximize terminal: ctrl+shift+;
  • Create new terminal: <leader>t n

Installation

  1. Copy settings.json to your VS Code user settings
  2. Copy keybindings.json to your VS Code keybindings
  3. Install required extensions:
    • Vim
    • GitLens (for enhanced git features)

Required Extensions

Key Concepts

  • Leader key is set to <space>
  • Consistent use of Vim navigation patterns
  • Integration with VS Code's native features
  • Enhanced terminal and git workflows

Common Workflows

File Navigation

  1. Open sidebar: <leader>e
  2. Navigate files: j/k
  3. Expand/collapse: l/h
  4. Open in split: ctrl+shift+1/2

Git Operations

  1. Stage changes: <leader>g s
  2. View changes: <leader>g d
  3. Push changes: <leader>g P

Code Navigation

  1. Go to definition: ctrl+]
  2. Return from definition: ctrl+t
  3. Find in workspace: <leader>s w

Customization

Edit the following files to customize the configuration:

  • settings.json: VS Code and Vim settings
  • keybindings.json: Custom keyboard shortcuts

Contributing

Feel free to submit issues and enhancement requests!

Changelog

All notable changes to this configuration will be documented in this file.

[1.0.0] - 2025-01-22

Added

  • Enhanced Git integration
    • Pull command: <leader>g p
    • Push command: <leader>g P
    • File history: <leader>g h
  • New navigation shortcuts
    • Method boundaries: [m, ]m
    • Error navigation: [d, ]d
    • Definition jumping: ctrl+], ctrl+t
  • Split management
    • Resize shortcuts: alt+h, alt+l
    • Maximize toggle: ctrl+w m
    • Equal sizing: <C-w>=
  • Code folding commands
    • Fold: <leader>z
    • Unfold: <leader>Z
  • Tab navigation
    • Previous/Next: alt+[, alt+]
  • Workspace management
    • Close workspace: ctrl+shift+w
    • Copy file path: ctrl+k p
  • Enhanced panel navigation
    • Consistent ctrl+j/k in all panels
    • Improved terminal focus controls

Changed

  • Standardized sidebar toggling to use <leader>e
  • Improved comments and documentation
  • Reorganized keybindings into logical groups

Fixed

  • Removed redundant keybindings
  • Standardized leader key usage
  • Improved context awareness for shortcuts

[0.1.0] - Initial Release

Added

  • Basic Vim keybindings
  • File explorer integration
  • Terminal shortcuts
  • Basic Git commands
  • Split navigation
[
//
// VIM NAVIGATION SHORTCUTS
//
{
// "ctrl+h": Focuses on the left editor group when the text editor is focused, Vim extension is active, and Vim is not in Insert mode
"key": "ctrl+h",
"command": "workbench.action.focusLeftGroup",
"when": "editorTextFocus && vim.active && vim.mode != 'Insert'"
},
{
// "ctrl+l": Focuses on the right editor group when the text editor is focused, Vim extension is active, and Vim is not in Insert mode
"key": "ctrl+l",
"command": "workbench.action.focusRightGroup",
"when": "editorTextFocus && vim.active && vim.mode != 'Insert'"
},
{
// "ctrl+k": Focuses on the editor group above when the text editor is focused, Vim extension is active, and Vim is not in Insert mode
"key": "ctrl+k",
"command": "workbench.action.focusAboveGroup",
"when": "editorTextFocus && vim.active && vim.mode != 'Insert'"
},
{
// "ctrl+j": Focuses on the editor group below when the text editor is focused, Vim extension is active, and Vim is not in Insert mode
"key": "ctrl+j",
"command": "workbench.action.focusBelowGroup",
"when": "editorTextFocus && vim.active && vim.mode != 'Insert'"
},
//
// CODE NAVIGATION AND EDITING
//
{
// "ctrl+space f": Formats the entire document
"key": "ctrl+space f",
"command": "editor.action.formatDocument",
"when": "editorTextFocus && !editorReadonly"
},
{
// "ctrl+]": Go to definition when hovering over a symbol
"key": "ctrl+]",
"command": "editor.action.revealDefinition",
"when": "editorHasDefinitionProvider && editorTextFocus"
},
{
// "ctrl+t": Go back to previous location after jumping to definition
"key": "ctrl+t",
"command": "workbench.action.navigateBack"
},
//
// SUGGESTIONS AND AUTOCOMPLETION SHORTCUTS
//
{
// "ctrl+j": Selects the next suggestion in the suggestions widget when it's visible
"key": "ctrl+j",
"command": "selectNextSuggestion",
"when": "suggestWidgetVisible"
},
{
// "ctrl+k": Selects the previous suggestion in the suggestions widget when it's visible
"key": "ctrl+k",
"command": "selectPrevSuggestion",
"when": "suggestWidgetVisible"
},
{
// "ctrl+j": Selects the next item in the Quick Open dialog when it's open
"key": "ctrl+j",
"command": "workbench.action.quickOpenSelectNext",
"when": "inQuickOpen"
},
{
// "ctrl+k": Selects the previous item in the Quick Open dialog when it's open
"key": "ctrl+k",
"command": "workbench.action.quickOpenSelectPrevious",
"when": "inQuickOpen"
},
//
// SEARCH AND NAVIGATION
//
{
// "ctrl+shift+f": Opens find in files with current word
"key": "ctrl+shift+f",
"command": "workbench.action.findInFiles",
"when": "editorFocus"
},
{
// "F4": Goes to next search result
"key": "F4",
"command": "editor.action.nextMatchFindAction",
"when": "editorFocus"
},
{
// "shift+F4": Goes to previous search result
"key": "shift+F4",
"command": "editor.action.previousMatchFindAction",
"when": "editorFocus"
},
//
// PROBLEM NAVIGATION
//
{
// "F8": Goes to next problem (error, warning) in the editor
"key": "F8",
"command": "editor.action.marker.nextInFiles",
"when": "editorFocus"
},
{
// "shift+F8": Goes to previous problem in the editor
"key": "shift+F8",
"command": "editor.action.marker.prevInFiles",
"when": "editorFocus"
},
//
// FILE EXPLORER SHORTCUTS
//
{
// "ctrl+shift+e": Focuses on File Explorer when text editor is focused
"key": "ctrl+shift+e",
"command": "workbench.files.action.focusFilesExplorer",
"when": "editorTextFocus"
},
{
// "ctrl+shift+e": Focuses back on active editor group when File Explorer is focused
"key": "ctrl+shift+e",
"command": "workbench.action.focusActiveEditorGroup",
"when": "explorerViewletVisible && filesExplorerFocus"
},
{
// "ctrl+shift+1": Opens selected file in the first (left) editor group from File Explorer
"key": "ctrl+shift+1",
"command": "explorer.openToSide",
"args": { "group": 0 },
"when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
},
{
// "ctrl+shift+2": Opens selected file in the second (right) editor group from File Explorer
"key": "ctrl+shift+2",
"command": "explorer.openToSide",
"args": { "group": 1 },
"when": "explorerViewletVisible && filesExplorerFocus && !inputFocus"
},
//
// FILE EXPLORER NAVIGATION SHORTCUTS
//
{
// "ctrl+h": Collapses the selected folder in File Explorer when list is focused and not in input mode
"key": "ctrl+h",
"command": "list.collapse",
"when": "listFocus && !inputFocus"
},
{
// "ctrl+l": Expands the selected folder in File Explorer when list is focused and not in input mode
"key": "ctrl+l",
"command": "list.expand",
"when": "listFocus && !inputFocus"
},
{
// "ctrl+k": Moves selection up in File Explorer when list is focused and not in input mode
"key": "ctrl+k",
"command": "list.focusUp",
"when": "listFocus && !inputFocus"
},
{
// "ctrl+j": Moves selection down in File Explorer when list is focused and not in input mode
"key": "ctrl+j",
"command": "list.focusDown",
"when": "listFocus && !inputFocus"
},
{
// "ctrl+enter": Initiates file rename when File Explorer is focused
"key": "ctrl+enter",
"command": "renameFile",
"when": "explorerViewletVisible && filesExplorerFocus"
},
{
// Disables the default "renameFile" command on enter key when File Explorer is focused
"key": "enter",
"command": "-renameFile",
"when": "explorerViewletVisible && filesExplorerFocus"
},
{
// "enter": Selects/opens the focused item in any list when not in input mode
"key": "enter",
"command": "list.select",
"when": "listFocus && !inputFocus"
},
//
// SPLIT MANAGEMENT
//
{
// "alt+h": Decreases the width of the current editor group
"key": "alt+h",
"command": "workbench.action.decreaseViewWidth"
},
{
// "alt+l": Increases the width of the current editor group
"key": "alt+l",
"command": "workbench.action.increaseViewWidth"
},
{
// "ctrl+w m": Toggles maximizing the current editor group
"key": "ctrl+w m",
"command": "workbench.action.toggleMaximizeEditorGroup"
},
//
// TAB MANAGEMENT
//
{
// "alt+[": Goes to previous editor in group
"key": "alt+[",
"command": "workbench.action.previousEditor"
},
{
// "alt+]": Goes to next editor in group
"key": "alt+]",
"command": "workbench.action.nextEditor"
},
//
// WORKSPACE MANAGEMENT
//
{
// "ctrl+shift+w": Closes current workspace
"key": "ctrl+shift+w",
"command": "workbench.action.closeFolder",
"when": "emptyWorkspaceSupport"
},
{
// "ctrl+k p": Copies the path of the active file
"key": "ctrl+k p",
"command": "workbench.action.files.copyPathOfActiveFile"
},
//
// TERMINAL SHORTCUTS
//
{
// "ctrl+;": Focuses the terminal when it's not currently focused
"key": "ctrl+;",
"command": "workbench.action.terminal.focus"
},
{
// "ctrl+;": Focuses back to the active editor group when terminal is focused
"key": "ctrl+;",
"command": "workbench.action.focusActiveEditorGroup",
"when": "terminalFocus"
},
{
// "ctrl+shift+;": Toggles terminal panel maximization and focuses on terminal
"key": "ctrl+shift+;",
"command": "multiCommand.toggleMaximizedPanelAndFocusTerminal",
"when": "!terminalFocus || terminalFocus"
},
//
// QUICK NAVIGATION SHORTCUTS
//
{
// "ctrl+1": Quickly focuses the first editor group (leftmost editor)
"key": "ctrl+1",
"command": "workbench.action.focusFirstEditorGroup"
},
{
// "ctrl+2": Quickly focuses the second editor group (right editor)
"key": "ctrl+2",
"command": "workbench.action.focusSecondEditorGroup"
},
//
// PANEL NAVIGATION SHORTCUTS
//
{
// "ctrl+j": Navigate to next panel item when panel is focused
"key": "ctrl+j",
"command": "list.focusDown",
"when": "panelFocus"
},
{
// "ctrl+k": Navigate to previous panel item when panel is focused
"key": "ctrl+k",
"command": "list.focusUp",
"when": "panelFocus"
}
]
{
// Editor Settings
// Display line numbers relative to the current cursor position
"editor.lineNumbers": "relative",
// Prevent scrolling beyond the last line of the file
"editor.scrollBeyondLastLine": false,
// Keep 8 lines visible above and below the cursor when scrolling
"editor.cursorSurroundingLines": 8,
// Enable smooth scrolling animation
"editor.smoothScrolling": true,
// Vim Configuration
// Enable easymotion plugin for quick navigation
"vim.easymotion": true,
// Enable incremental search highlighting
"vim.incsearch": true,
// Use system clipboard for vim operations
"vim.useSystemClipboard": true,
// Enable Ctrl key combinations
"vim.useCtrlKeys": true,
// Enable search highlight
"vim.hlsearch": true,
// Set space as the leader key
"vim.leader": " ",
// Enable vim-sneak plugin for improved motion
"vim.sneak": true,
// Use relative line numbers in normal mode
"vim.smartRelativeLine": true,
// Handle specific keys
"vim.handleKeys": {
// Keep Ctrl+d for scrolling down
"<C-d>": true,
// Keep Ctrl+u for scrolling up
"<C-u>": true,
// Disable Ctrl+f to use VS Code's find instead
"<C-f>": false
},
// Insert Mode Keybindings
"vim.insertModeKeyBindings": [
{
// Exit insert mode by pressing 'j' twice quickly
"before": ["j", "j"],
"after": ["<Esc>"]
}
],
// Normal Mode Keybindings
"vim.normalModeKeyBindingsNonRecursive": [
// Basic Operations
{
// Delete current line with leader+d
"before": ["<leader>", "d"],
"after": ["d", "d"]
},
{
// Clear search highlighting with Ctrl+n
"before": ["<C-n>"],
"commands": [":nohl"]
},
{
// Insert line break above cursor with K
"before": ["K"],
"commands": ["lineBreakInsert"],
"silent": true
},
// Window Management
{
// Split editor with leader+w
"before": ["<leader>", "w"],
"commands": ["workbench.action.splitEditor"]
},
{
// Save current file with leader+w+w
"before": ["<leader>", "w", "w"],
"commands": [":w"]
},
// Sidebar and Explorer
{
// Toggle sidebar and focus explorer with leader+e
"before": ["<leader>", "e"],
"commands": ["workbench.action.toggleSidebarVisibility", "workbench.files.action.focusFilesExplorer"]
},
{
// Reveal current file in explorer with leader+f
"before": ["<leader>", "f"],
"commands": ["revealInExplorer"]
},
// File Operations
{
// Copy current file path with leader+f+y
"before": ["<leader>", "f", "y"],
"commands": ["copyFilePath"]
},
{
// Create new file in current directory with leader+f+n
"before": ["<leader>", "f", "n"],
"commands": ["explorer.newFile"]
},
// Code Actions
{
// Toggle line comment with leader+c
"before": ["<leader>", "c"],
"commands": ["editor.action.commentLine"]
},
{
// Rename symbol with leader+r+e
"before": ["<leader>", "r", "e"],
"commands": ["editor.action.rename"]
},
{
// Rename file with leader+r+f
"before": ["<leader>", "r", "f"],
"commands": ["fileutils.renameFile"]
},
// Navigation
{
// Go to previous method with [m
"before": ["[", "m"],
"commands": ["editor.action.previousMethodOrAttributeKeys"]
},
{
// Go to next method with ]m
"before": ["]", "m"],
"commands": ["editor.action.nextMethodOrAttributeKeys"]
},
{
// Go to next problem/error with ]d
"before": ["]", "d"],
"commands": ["editor.action.marker.next"]
},
{
// Go to previous problem/error with [d
"before": ["[", "d"],
"commands": ["editor.action.marker.prev"]
},
// Search and Symbols
{
// Show all symbols in workspace with leader+o+g
"before": ["<leader>", "o", "g"],
"commands": ["workbench.action.showAllSymbols"]
},
{
// Show all editors in active group with leader+o+o
"before": ["<leader>", "o", "o"],
"commands": ["workbench.action.showEditorsInActiveGroup"]
},
{
// Open quick open panel with leader+o+p
"before": ["<leader>", "o", "p"],
"commands": ["workbench.action.quickOpen"]
},
{
// Search word under cursor in workspace with leader+s+w
"before": ["<leader>", "s", "w"],
"commands": ["editor.action.addSelectionToNextFindMatch", "workbench.action.findInFiles"]
},
// Code Folding
{
// Fold code with leader+z
"before": ["<leader>", "z"],
"commands": ["editor.fold"]
},
{
// Unfold code with leader+Z
"before": ["<leader>", "Z"],
"commands": ["editor.unfold"]
},
// Git Integration
{
// Toggle git blame with leader+g+b
"before": ["<leader>", "g", "b"],
"commands": ["gitlens.toggleFileBlame"]
},
{
// Show git diff with leader+g+d
"before": ["<leader>", "g", "d"],
"commands": ["workbench.action.compareEditor.previousChange"]
},
{
// Stage current file with leader+g+s
"before": ["<leader>", "g", "s"],
"commands": ["git.stage"]
},
{
// Git pull with leader+g+p
"before": ["<leader>", "g", "p"],
"commands": ["git.pull"]
},
{
// Git push with leader+g+P
"before": ["<leader>", "g", "P"],
"commands": ["git.push"]
},
{
// Show file history with leader+g+h
"before": ["<leader>", "g", "h"],
"commands": ["git.viewFileHistory"]
},
// Terminal
{
// Create new terminal and focus with leader+t+n
"before": ["<leader>", "t", "n"],
"commands": ["multiCommand.newTerminalAndFocus"]
},
// Debug
{
// Toggle breakpoint with leader+b
"before": ["<leader>", "b"],
"commands": ["editor.debug.action.toggleBreakpoint"]
},
{
// Continue debugging with leader+d+c
"before": ["<leader>", "d", "c"],
"commands": ["workbench.action.debug.continue"]
},
{
// Step over in debug mode with leader+d+n
"before": ["<leader>", "d", "n"],
"commands": ["workbench.action.debug.stepOver"]
},
// Split Management
{
// Equalize editor widths with ctrl+w =
"before": ["<C-w>", "="],
"commands": ["workbench.action.evenEditorWidths"]
},
// Bookmarks
{
// Toggle bookmark 1 with m+a
"before": ["m", "a"],
"commands": ["numberedBookmarks.toggleBookmark1"]
}
],
// Visual Mode Keybindings
"vim.visualModeKeyBindings": [
{
// Comment selected lines and exit visual mode with leader+c
"before": ["<leader>", "c"],
"commands": ["editor.action.commentLine", "extension.vim_escape"]
},
{
// Select all occurrences of current selection with leader+a
"before": ["<leader>", "a"],
"commands": ["editor.action.selectHighlights"]
}
],
// Multi-command Configuration
"multiCommand.commands": [
{
// Toggle maximized terminal panel and focus terminal
"command": "multiCommand.toggleMaximizedPanelAndFocusTerminal",
"sequence": [
"workbench.action.toggleMaximizedPanel",
"workbench.action.terminal.focus"
]
},
{
// Create new terminal and focus it
"command": "multiCommand.newTerminalAndFocus",
"sequence": [
"workbench.action.terminal.new",
"workbench.action.terminal.focus"
]
}
]
}
@nicolidin
Copy link

hello it seems i can't have two keys after leader, only one works, how did you do?

@w3sync
Copy link

w3sync commented Sep 23, 2024

hey some features are missing like ctrl+f, ctrl+s,

@wojukasz
Copy link
Author

wojukasz commented Oct 2, 2024

@nicolidin you have to install multi-command plugin and add the multi-command settings https://gist.github.com/wojukasz/d76ca3162debc66d4227b9dc6049789e#file-settings-json

@wojukasz
Copy link
Author

hey some features are missing like ctrl+f, ctrl+s,

yeah, its not something I explored yet but I will try build upon this config over time

@DmitriiKozlov-Neura
Copy link

I changed the ', e' binding, to be able to input commas in terminal. Added !inputFocus to when:

 {
    // ", e": Toggles the sidebar's visibility when the text editor is not focused. <leader> + e
    "key": ", e",
    "command": "workbench.action.toggleSidebarVisibility",
    "when": "!editorTextFocus && !inputFocus"
  },

@wojukasz
Copy link
Author

I changed the ', e' binding, to be able to input commas in terminal. Added !inputFocus to when:

 {
    // ", e": Toggles the sidebar's visibility when the text editor is not focused. <leader> + e
    "key": ", e",
    "command": "workbench.action.toggleSidebarVisibility",
    "when": "!editorTextFocus && !inputFocus"
  },

Nice! thanks for sharing!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment