I recently decided that putting strategically placed print statements scattered about my python programs to debug was getting to be a little messy.
I had thought to try out other debugging plugins I found online, but thought I would give writing my own simple breakpoint plugin a shot.
I know of python's pdb module, but my goal was to minimize the amount that I had to type to debug my programs.
Only a few keybinds are mapped:
Normal mode:
<leader>b— Toggle breakpoint for the current line<leader>B— Run debugger in a new tmux split
Visual Mode:
<leader>b— Toggle breakpoint for the selected lines
This has only been tested on Linux. The only requirement is tmux
" Define breakpoint highlight color and mark in number column
hi Breakpoint ctermfg=1 ctermbg=NONE
sign define Breakpoint text=● texthl=Breakpoint
" Map of lines that have breakpoints
let b:breakpoints = {}
function ToggleBreakpoint(lnum)
let is_breakpoint = get(b:breakpoints, a:lnum, 0)
if is_breakpoint
" Remove the line number in breakpoints and unplace the mark
call remove(b:breakpoints, a:lnum)
exe ":sign unplace"
else
" Add the line number in breakpoints and place the mark
let b:breakpoints[a:lnum] = 1
exe ":sign place 2 line=" . a:lnum . " name=Breakpoint file=" . expand("%:p")
endif
endfunction
function BreakpointIndentation(lnum)
" Get the line's current indentation level and first character
let indent_count = indent(a:lnum)
let curline = getline(a:lnum)
let firstChar = curline[0]
" Build the indentation to use for the breakpoint
if firstChar == "\t"
" Handle user defined `tabstop` variable
return repeat(firstChar, indent_count / &tabstop)
else if firstChar == " "
return repeat(firstChar, indent_count)
else
return ""
endif
endfunction
function RunPDB()
let lnum = 1
let num_lines = line("$")
" The lines to write to the temporary file
" Start out by importing pdb
let lines = ["import pdb"]
" Iterate over each line in the current buffer
while lnum <= num_lines
let is_breakpoint = get(b:breakpoints, lnum, 0)
" If the line is a breakpoint, add `pdb.set_trace` before that line
if is_breakpoint
let indentation = BreakpointIndentation(lnum)
let breakpoint_line = "pdb.set_trace()"
if indentation != ""
let breakpoint_line = indentation . breakpoint_line
endif
call add(lines, breakpoint_line)
endif
call add(lines, getline(lnum))
let lnum += 1
endwhile
" Create a new temporary file with the contents of `lines`
let tmpfile = tempname()
call writefile(lines, tmpfile)
" Make a new vertical tmux split and run the temporary file with python
silent exe "!tmux split-pane -v"
silent exe "!tmux send-keys 'python " . tmpfile . "' Enter"
endfunction
nnoremap <leader>b :call ToggleBreakpoint(line("."))<CR>
vnoremap <leader>b :call ToggleBreakpoint(line("."))<CR>
nnoremap <leader>B :call RunPDB()<CR>
This is my first attempt to write anything particularly useful in vimscript.
Are there any sections that can be improved upon?