Neovim中配置光标到自定义标记的代码段选区快捷键方案
Hey there! Great setup with tmux + Neovim + IPython—this combo is perfect for data work. Let's solve your problem of selecting and running code between custom markers efficiently, using Vim's built-in fold system (which plays nicely with your foldmarker config) and vim-slime.
Core Idea: Leverage Vim's Marker Folding
Instead of writing custom regex to find markers, we can use Vim's existing marker fold method. This automatically respects your foldmarker setting, works with nested segments, and only targets the fold your cursor is currently in.
Step 1: Configure Folding (if not already done)
First, make sure you have marker folding enabled and set your desired markers. Add this to your init.lua (or init.vim):
Lua:
-- Enable marker-based folding vim.opt.foldmethod = 'marker' -- Set your custom markers (adjust to your preference) vim.opt.foldmarker = '#$%,#$%' -- Same start/end marker -- OR for different start/end: vim.opt.foldmarker = '{{{,}}}'
Vimscript:
set foldmethod=marker set foldmarker=#$%,#$% " Same start/end marker " OR set foldmarker={{{,}}} " Different start/end
Step 2: Add Custom Selection Function & Keybind
We'll create a function to select the content inside the current fold (excluding the markers) and map it to <leader>s.
Lua (add to init.lua):
-- Function to select content inside the current fold local function select_current_fold_content() local start_line = vim.fn.foldstart(vim.fn.line('.')) local end_line = vim.fn.foldend(vim.fn.line('.')) -- If not in a fold, select current line as fallback if start_line == -1 or end_line == -1 then vim.api.nvim_command('normal! V') return end -- Move cursor to start of content and select to end of content vim.api.nvim_win_set_cursor(0, {start_line + 1, 0}) vim.api.nvim_command('normal! V' .. (end_line - 1) .. 'G') end -- Map <leader>s to select fold content vim.keymap.set('n', '<leader>s', select_current_fold_content, { desc = 'Select content between custom markers (current fold)' })
Vimscript (add to init.vim):
function! SelectCurrentFoldContent() let start_line = foldstart(line('.')) let end_line = foldend(line('.')) if start_line == -1 || end_line == -1 normal! V return endif execute "normal! " . (start_line + 1) . "GV" . (end_line - 1) . "G" endfunction nnoremap <leader>s :call SelectCurrentFoldContent()<CR>
Step 3: Integrate with vim-slime (One-Step Run)
To send the selected content directly to IPython without extra steps, add a keybind that selects the fold content and sends it via vim-slime.
Lua:
local function select_and_send_to_slime() select_current_fold_content() vim.api.nvim_command('SlimeSend') end -- Map <leader>r to run the current fold's content vim.keymap.set('n', '<leader>r', select_and_send_to_slime, { desc = 'Send current fold content to IPython via vim-slime' })
Vimscript:
function! SelectAndSendToSlime() call SelectCurrentFoldContent() call SlimeSend() endfunction nnoremap <leader>r :call SelectAndSendToSlime()<CR>
How It Works
- When you press
<leader>sin normal mode, it selects the content between the nearest marker pair that contains your cursor (ignoring the markers themselves). - If your cursor isn't in a marked segment, it falls back to selecting the current line.
<leader>rdoes the same selection and immediately sends it to your IPython session via vim-slime.
Bonus Tips
- Nested Folds: This setup automatically selects the innermost fold your cursor is in—perfect if you have nested code segments.
- Toggle Folds: Use
zato toggle folding of the current segment, which helps visualize your code structure. - vim-slime Config: Ensure vim-slime is set up to target your IPython session in tmux. A common config is:
vim.g.slime_target = 'tmux' vim.g.slime_default_config = {socket_name = 'default', target_pane = '{last}'}
This approach is clean, maintainable, and leverages Vim's built-in features instead of reinventing the wheel with custom regex searches.
内容的提问来源于stack exchange,提问作者xxyxxyxyx1

