dikiy_mujchina: (Default)
[personal profile] dikiy_mujchina
Bash debugger базований на редакторі vim

Огляд
Ми часто використовуємо опції bash для того, щоб налагоджувати скрипти, але іноді це не комфортно.
Якщо ви володієте редактором vim, тоді ви зможете легко і якісно дебажити скрипти прямо з редактора!

Вам треба виконати всього дві дії:
1. Додати команди до  ~/.vimrc
2. Створити скрипт debugger.sh у теці ~/.vim

Що може даний налагоджувач?

1. Порядкове виконання скрипту
2. Переглядати значення вказаних змінних після кожного кроку виконання
3. Створювати місця зупинки виконання скрипту візуально у редакторі
4. Виконувати скрипт до наступного місця зупинки(якщо воно є)
5. Вмикання.вимикання трасування всередині функцій
6. Виконувати скрипт без налагоджувача
7. Видаляти всі помітки(місця зупинки, перемикання трасування функцій)

Клавіші керування налагоджувачем

F9 - Видалення всіх міток
F8 - Виконання скрипту без налагоджувача
F7 - Виконання скрипту з налагоджувачем
F6 - Показати/приховати вікно з змінними для стеження. Кожна змінна має бути визначена без пропусків, {}, $, тощо.
Приклад:
A
B[1]
C[@]

F5 - Вставити/прибрати місце зупинки виконання скрипту в даному рядку..
F4 - Увімкнути/вимкнути трасування функцій.

Як встановити налагоджувач?

1. Додайте наступні рядки до  ~/.vimrc:

:set number

" Underline current line
augroup CursorLine
 au!
 au VimEnter,WinEnter,BufWinEnter * setlocal cursorline
 au WinLeave * setlocal nocursorline
augroup END

" Write&Quit to ~/.vim/variables if it lost focus
augroup VariablesFile
  au WinLeave ~/.vim/variables wq
augroup END

" Trace script
fu! Trace()
  " Save output of 'sign place' to file
  redir > ~/.vim/places
   execute "silent sign place file=" . expand("%:p")
  redir end
  " Save script to temporary file
  execute ":w! ~/.vim/bash.debug.sh"
  " Run debugger
 execute ":! ~/.vim/debuger.sh"
endfunction

" Run script w/o trace
fu! Execute()
 silent execute ":!clear"
  " Save script to temporary file
  execute ":w! ~/.vim/bash.debug.sh"
  " Set executing permitions
  silent execute ":! chmod 755 ~/.vim/bash.debug.sh"
  " Run script
  execute ":! ~/.vim/bash.debug.sh"
  " Remove temporary script
  silent execute ":! rm -f ~/.vim/bash.debug.sh"
endfunction

" Show/hide window with variables
fu! Variables()
 " If current file is './vim/variables'
 if expand('%:p:h:t') == ".vim"
  if expand('%:t') == "variables"
   " Save&Quit
   execute ":wq!"
  else
   " Open new window
   copen
   " Load file with variables
   execute ":e ~/.vim/variables"
  endif
 else
  " Open new window
  copen
  " Load file with variables
  execute ":e ~/.vim/variables"
 endif
endfunction

" Enable/Disable breakpoint
fu! Breakpoint()
 " Get current line
 let currentrow = line(".")
 " Remove file
 silent execute ":! rm -f ~/.vim/places"
 " Save output of 'sign place' to file
 redir >~/.vim/places
  execute ":silent sign place file=" . expand("%:p")
 redir end
 " Parse file and save sign's name to variable signname
 let signname=system("grep '=".currentrow.".*id=.*breakpoint' ~/.vim/places | awk '{printf $3}' | sed 's/^.*=//'")
 if empty(signname)
  " If not exist sign name in current line
  " Define breakpoint
  execute ":sign define breakpoint" . currentrow . " text=BP texthl=Search linehl=Search"
  " Place sign to current line
  execute ":sign place ".currentrow." line=".currentrow." name=breakpoint".currentrow." file=".expand("%:p")
 else
  " If exist sign name in current line then undefine it
  exec ":sign undefine ".signname
 endif
 " Remove file
 silent execute ":! rm -f ~/.vim/places"
 " Redraw screen
 redraw!
endfunction

" Enable/Disable function trace
fu! FuncTrace()
 " Remove file
 silent execute ":! rm -f ~/.vim/places"
 " Save output of 'sign place' to file
 redir >~/.vim/places
 execute ":silent sign place file=" . expand("%:p")
 redir end
 " Parse file and save sign's name to variable signname
 let signname=system("grep '=1.*id=1.*functrace' ~/.vim/places | awk '{printf $3}' | sed 's/^.*=//'")
 if empty(signname)
  " If not exist sign name in current line
  " Define breakpoint
  execute ":sign define functrace text=FT texthl=Error"
  execute ":sign place 1 line=1 name=functrace file=" . expand("%:p")
 else
  " If exist sign name in current line then undefine it
  execute ":sign undefine functrace"
 endif
 " Remove file
 silent execute ":! rm -f ~/.vim/places"
 " Redraw screen
 redraw!
endfunction

" Unmark all signs
fu! Unmark()
 " Remove all signs
 execute ":sign unplace *"
 " Redraw screen
 redraw!
endfunction

" Undefine all marks
nmap :call Unmark()
" Run script without debuging
nmap :call Execute()
" Run script with debuging
nmap :call Trace()
" Show or hide variables list
nmap :call Variables()
" Mark/Unmark BreakPoint
nmap :call Breakpoint()
" Mark/Unmark Function trace
nmap :call FuncTrace()

:set number та augroup CursorLine блок можуть бути видаленими. Але з ними зручніше працювати у редакторі.

2. Створіть скрипт debugger.sh в теці ~/.vim/

#!/bin/bash
########
# Bash debugger for Vim v. 1.0
# Created by Oleksandr Mishchenko (c) 2018
# sasha.mishchenko@gmail.com
# Published under GPL license
########
clear
echo Executing in trace mode.
echo "Press 'Space' key to execute one line, Press 'g' key to execute to next break point."
if grep functrace ~/.vim/places &>/dev/null
then
  sed "1a set -o functrace;trap 'rm -f ~/.vim/{places,bash.debug2.sh} &>/dev/null' EXIT;trap 'typeset -A mydebug_BP;while read mydebug_LINE; do ((\$mydebug_LINE>0)) 2>/dev/null && mydebug_BP[\$mydebug_LINE]=1;done < <(cat ~/.vim/places | grep \"id=.*breakpoint\" | awk \"{ print \\\\\$1 }\" | sed \"s/^.*=//\");while read mydebug_VAR; do echo -en \"\\\e[0;32m\$mydebug_VAR:\\\e[1;32m\${!mydebug_VAR}\\\e[0m \";done < ~/.vim/variables;echo; echo -e \"\\\e[0;33m\$((LINENO-1)) \\\e[1;33m\$BASH_COMMAND\\\e[0m\"; if [[ \"\${mydebug_BP[\$((LINENO-1))]}\" == 1 ]]; then mydebug_KEY=\"\"; fi; until [[ \"\$mydebug_KEY\" == \" \" || \"\$mydebug_KEY\" == \"g\" ]]; do read -sN1 mydebug_KEY;done; [[ \"\$mydebug_KEY\" == \" \" ]] && mydebug_KEY=\"\"' DEBUG" ~/.vim/bash.debug.sh > ~/.vim/bash.debug2.sh
else
  sed "1a trap 'rm -f ~/.vim/{places,bash.debug2.sh} &>/dev/null' EXIT;trap 'typeset -A mydebug_BP;while read mydebug_LINE; do ((\$mydebug_LINE>0)) 2>/dev/null && mydebug_BP[\$mydebug_LINE]=1;done < <(cat ~/.vim/places | grep \"id=.*breakpoint\" | awk \"{ print \\\\\$1 }\" | sed \"s/^.*=//\");while read mydebug_VAR; do echo -en \"\\\e[0;32m\$mydebug_VAR:\\\e[1;32m\${!mydebug_VAR}\\\e[0m \";done < ~/.vim/variables;echo; echo -e \"\\\e[0;33m\$((LINENO-1)) \\\e[1;33m\$BASH_COMMAND\\\e[0m\"; if [[ \"\${mydebug_BP[\$((LINENO-1))]}\" == 1 ]]; then mydebug_KEY=\"\"; fi; until [[ \"\$mydebug_KEY\" == \" \" || \"\$mydebug_KEY\" == \"g\" ]]; do read -sN1 mydebug_KEY;done; [[ \"\$mydebug_KEY\" == \" \" ]] && mydebug_KEY=\"\"' DEBUG" ~/.vim/bash.debug.sh > ~/.vim/bash.debug2.sh
fi
rm -f ~/.vim/bash.debug.sh &>/dev/null
chmod 700 ~/.vim/bash.debug2.sh
~/.vim/bash.debug2.sh

Встановіть права на виконання скрипта:
chmod 755 debugger.sh

Особливості

1. Поки налагоджувач працює лише для одного скрипта. Якщо паралельно налагоджувати 2 скрипти під одним користувачем, то у них будуть спільні місця зупинки, змінні спостереження, тощо.

2. Місця зупинки не діють на командах return, fi, then, else та інших складених bash командах. Це зумовлене тим, що так працює обробка сигналу DEBUG в команді trap в bash. Також ви не зможете зупинити виконання скрипту на рядку, що не містить команд, або містить лише коментарі. При потребі зупинитися в даних місцях, можете тимчасово ставити команду : . Дана команда нічого не робить, проте на ній налагоджувач може зупинятися.

3. Налагоджувач не відслідковує зміст скрипту. Тобто якщо в редакторі буде конфігураційний файл і ви його виконаєте, то він буде переданий інтерпретатору bash на виконання і буде ним відповідно оброблений.


Date: 2018-08-11 12:26 am (UTC)

bytebuster: (Keaton-Chase)
From: [personal profile] bytebuster
Мамадарагая, це… просто круто!
Таким чайникам, як я, які через усі Башеві конструкції продираються як через тернії, таке дуже корисно. Дякую!

Ще б якби хтось причепив його плугіном до far2l — ващє була б красота. Autocomplete туди, нарешті, приліплено десь півроку тому, працює.

Про мене

dikiy_mujchina: (Default)
dikiy_mujchina

December 2019

S M T W T F S
1234 567
891011121314
15161718192021
22232425262728
293031    

Мітки

Резюме сторінки

За стиль дякую

Показати приховане

No cut tags
Page generated May. 24th, 2025 11:52 pm
Powered by Dreamwidth Studios