aboutsummaryrefslogtreecommitdiff
path: root/content/weblog
diff options
context:
space:
mode:
authorYaroslav de la Peña Smirnov <yps@yaroslavps.com>2022-01-25 22:54:56 +0300
committerYaroslav de la Peña Smirnov <yps@yaroslavps.com>2022-01-25 22:54:56 +0300
commitb623aec3cbe0ea2edbecffc16e58296646ba5353 (patch)
tree5b83980820065307d81a9acba72c4b9fdd986360 /content/weblog
parent6a130c7d04138a08ec2b80e1d4164ff48bcc7e0f (diff)
downloadyaroslavps.com-b623aec3cbe0ea2edbecffc16e58296646ba5353.tar.gz
yaroslavps.com-b623aec3cbe0ea2edbecffc16e58296646ba5353.zip
How I debug programs in Vim
Diffstat (limited to 'content/weblog')
-rw-r--r--content/weblog/2022-01-25_debugging-in-vim/debugging-session.pngbin0 -> 322587 bytes
-rw-r--r--content/weblog/2022-01-25_debugging-in-vim/index.md234
-rw-r--r--content/weblog/2022-01-25_debugging-in-vim/index.ru.md237
-rw-r--r--content/weblog/2022-01-25_debugging-in-vim/quit-vim.jpgbin0 -> 17067 bytes
4 files changed, 471 insertions, 0 deletions
diff --git a/content/weblog/2022-01-25_debugging-in-vim/debugging-session.png b/content/weblog/2022-01-25_debugging-in-vim/debugging-session.png
new file mode 100644
index 0000000..6dbf16c
--- /dev/null
+++ b/content/weblog/2022-01-25_debugging-in-vim/debugging-session.png
Binary files differ
diff --git a/content/weblog/2022-01-25_debugging-in-vim/index.md b/content/weblog/2022-01-25_debugging-in-vim/index.md
new file mode 100644
index 0000000..a281e6d
--- /dev/null
+++ b/content/weblog/2022-01-25_debugging-in-vim/index.md
@@ -0,0 +1,234 @@
++++
+title = "How I debug programs in Vim"
+date = 2022-01-25T19:49:30Z
++++
+
+I like to use separate tools for different tasks, and also like it when those
+tools integrate with the other tools I use. Unfortunately I haven't seen much
+information online for possible workflows on debugging programs with Vim. There
+is information but it is all spread out. So I decided to write about the
+workflow that I've built over the years for writing and debugging programs with
+Vim.
+
+<!-- more -->
+
+Many, or most, IDEs already come with some sort of debugging facility. But
+those IDEs are not vim, and more often than not, they also come with a lot of
+other features that frankly are not very useful. And no, vimifcation plugins
+don't count, most of them don't cover even half the functionality that vim
+offers.
+
+I love using vim (technically neovim, eh, same diff), I really think that it is
+the best text editor out there. Hell, I even, unironically, think it might the
+program with best UI/UX. Sure it is not intuitive at all ([insert obligatory
+exit vim meme](#exit-vim)), but once you learn the ropes of it, and it doesn't
+take as long as
+they meme it to be, it's just bliss. In shot, vim is a lifestyle, not a program.
+
+The problem is that learning to be a power user of vim can take time. And to be
+able to efficiently develop programs typing them is not enough. You also need
+to navigate around code bases, quickly fix the most basic of errors (such as
+typos), reduce repetitive tasks (e.g. autocomplete), and of course, debug and
+profile.
+
+Fortunately both vim and neovim, for at least some 3–4 years now, offer
+facilities to integrate software development and debugging tools with ease.
+Since I use neovim, some things that I talk about here might differ a little
+bit.
+
+## Development tools
+
+It used to be that each editor/IDE needed to have plugins developed for, or even
+baked into, them individually. This meant that efforts had to split for every
+and each language and editor combination, which meant that not every editor had
+support even every popular language.
+
+Fortunately, Microsoft did a very un-Microsoft thing, and instead of baking in
+another completely new implementation of IDE-like development tools for each
+language to their VSCode editor, they developed what now is called the Language
+Server Protocol[^1], and with the help of Red Hat et al they open sourced it and
+standardized it.
+
+In short, the Language Server Protocol (LSP) is just a JSON RPC protocol for
+communications between a server that provides the functions, such as
+autocompletion, linting, go-to-definition, etc. and the client which would be
+the IDE or editor, which basically displays the results. And one of the editors
+that supports LSP is vim. In fact, at least in neovim, the support is built in.
+
+### LSP
+
+In order to use LSP in neovim, you need to enable the plugin and configure the
+LSP server(s) for your language(s). The good thing is that configuring it is
+pretty simple and straightforward, especially since there is a plugin that
+already comes with default configurations for a lot of popular languages LSPs.
+
+I use [vim-plug](https://github.com/junegunn/vim-plug) to manage my plugins, so
+first I added the official [lspconfig](https://github.com/neovim/nvim-lspconfig)
+plugin:
+
+```vim
+"...
+ Plug 'neovim/nvim-lspconfig'
+"...
+```
+
+And then proceeded to configure it for my needs by adding the configurations for
+the LSP servers for C, Go, Rust, Python and Javascript, the languages that I use
+the most often:
+
+```vim
+" LSP
+ set omnifunc=v:lua.vim.lsp.omnifunc
+ lua require('lspconfig').clangd.setup{filetypes = { "c", "cpp", "objc", "objcpp", "ch" }}
+ lua require('lspconfig').gopls.setup{}
+ lua require('lspconfig').pylsp.setup{}
+ lua require('lspconfig').rls.setup{}
+ lua require('lspconfig').tsserver.setup{}
+
+" LSP keybinds
+ nmap <silent> gd <cmd>lua vim.lsp.buf.definition()<CR>
+ nmap <silent> gD <cmd>lua vim.lsp.buf.declaration()<CR>
+ nmap <silent> gK <cmd>lua vim.lsp.buf.hover()<CR>
+ nmap <silent> <leader>n <cmd>lua vim.lsp.buf.rename()<CR>
+ nmap <silent> <leader>b <cmd>lua vim.lsp.buf.formatting()<CR>
+
+" neovim overrides my omnifunc with whatever ccomplete is, so I use this
+ autocmd FileType c,ch,header,cpp setlocal omnifunc=v:lua.vim.lsp.omnifunc
+```
+
+Of course, in order to use the functionality, you also need to have the LSP
+servers installed in your system. In the case of Go, it comes with the standard
+toolchain, same as with Rust. For C, you will need clang, as far as I know GCC
+doesn't provide an LSP implementation.
+
+The keybindings in my config make it so that I can go to definition with `gd`,
+go to declaration with `gD`, get a popup with information implementations and
+comment documentation with `gK`, rename variables with `<leader>n` (leader is
+space in my config) and process the file through a formatting tool (e.g. gofmt)
+with `<leader>b`.
+
+### Other plugins
+
+Now, LSP provides most of the functions you would expect from an IDE, but there
+are still some other plugins that I use for better quality of life. Namely:
+
+```vim
+"...
+ Plug 'ervandew/supertab'
+ Plug 'majutsushi/tagbar'
+ Plug 'tpope/vim-commentary'
+"...
+```
+
+The first one, [supertab](https://github.com/ervandew/supertab), makes using
+autocompletion much more comfy. By default the omnifunc autocomplete is bound to
+\<C-x\>\<C-o\> which is not very comfortable to enter. Usually, in shells and
+other editors, you use Tab to autocomplete, which is a pretty sane way to do it.
+But sometimes you actually need to insert tabs manually. That's where this
+plugin comes in, since it intelligently chooses whether to insert a tab, or
+autocomplete on pressing the Tab key.
+
+The next is [tagbar](https://github.com/preservim/tagbar). This plugin allows
+you to open up a sidebar of sorts that lists the global variables,
+data/struct/type definitions, and functions in the current source file. It
+requires a ctags implementation to work.
+
+Finally is [vim-commentary](https://github.com/tpope/vim-commentary), which
+provides an easy way to comment out multiple lines easily. Not AS useful as the
+other ones, but still handy nonetheless.
+
+## Debugging
+
+Sooner or later when writing programs and testing them you come across some kind
+of programming error that causes it to misbehave. You can try to find the
+problem manually by looking at the code and scratching your head, but a much
+better way is to fire up a debugger and go step-by-step over the program
+execution in search of your bug.
+
+For some time, at least for C and other languages that are supported by it, I
+would just open gdb in a different terminal window and keep my source file open
+in vim in another. But a couple of additions were made to both vim and neovim
+which made it much pleasurable to debug programs.
+
+The first is `terminal` which, just as its name implies, is a terminal emulator
+inside vim. Basically it allows you to open a terminal inside a vim buffer. For
+me personally this feature by itself is not of great use, since I use a tiling
+WM which already makes it much more comfortable for me to move around terminals.
+However, it gives way to a plugin that is much more useful, and which depends on
+this functionality.
+
+Introducing `Termdebug`. This is a plugin which is built into both Vim (version
+>= 8.1) and Neovim. What it basically does is it opens two split windows, one
+with gdb and the second one with the output of your program. You can then input
+gdb commands directly into the gdb console, or through some vim-provided
+shortcuts.
+
+In order to start using Termdebug, you need to first load the plugin:
+
+```vim
+:packadd termdebug
+```
+
+And then load it providing the name of the binary that is going to be executed
+by gdb:
+
+```vim
+:Termdebug <path to binary>
+```
+
+You will be greeted with two new split buffers, one with the program output and
+the other with a gdb console. They are both terminal buffers. The way you use
+those terminal buffers in vim is, you enter insert mode to type into the
+terminal, and exit insert mode with \<C-\\\>\<C-n\>. Why not escape? Because
+some terminal programs make use of escape, for example, vi mode in bash or zsh.
+Or maybe even another vim instance inside vim, why not ¯\\_(ツ)_/¯.
+
+After having opened Termdebug, you can run the program the classic way from gdb.
+Or from within vim with `:Run <args>`. Other useful shortcuts are `:Break` to
+set a breakpoint at the current line of code, `:Clear` to delete a breakpoint at
+the current line if there's any, `:Continue` to resume program execution, etc.
+
+[![A screenshot of an example debugging session](debugging-session.png)](debugging-session.png)
+<figcaption>
+
+An example debugging session.
+</figcaption>
+
+What makes this really wonderful is the fact that you see the process of
+debugging straight in your source file. You don't have to constantly list the
+code inside gdb, and you can just navigate around files to set or clear
+breakpoints.
+
+Of course, since you're just debugging programs with gdb the usual rules of
+debugging with gdb apply. For example, you need to compile your program with
+debugging symbols, i.e. with the `-g` flag.
+
+## Afterword
+
+These are just of the plugins and configurations that use in vim to help me
+write and debug software. This is, of course not meant as an in-depth tutorial
+or guide on how to configure vim or how to properly debug programs. This is
+just a mere guide on how one can use vim in conjunction with other tools to
+develop and debug programs. There's a lot of information on the internet on how
+to configure vim or how to debug programs with gdb, and using other tools such
+as valgrind and ASan.
+
+If you want to know more about lsp in neovim, you can read the help page inside
+neovim by entering `:help lsp`. The same goes with Termdebugger: `:help
+Termdebugger`.
+
+If you are interested, you can check my full neovim config here:
+<https://git.yaroslavps.com/configs/vimrice/>
+
+<figcaption id="exit-vim">
+
+![How to exit vim](quit-vim.jpg)
+
+If you have never used Vim before, and this article caused you to open it in a
+whim and now you can't exit it, this picture might be helpful.
+</figcaption>
+
+[^1]: Not completely Unix-y, but somewhat adherent to the Unix philosophy in the
+ sense that one program should do one thing and do it right. A shock coming
+ from Microsoft, I know. You can learn more about it here:
+ <https://microsoft.github.io/language-server-protocol/>
diff --git a/content/weblog/2022-01-25_debugging-in-vim/index.ru.md b/content/weblog/2022-01-25_debugging-in-vim/index.ru.md
new file mode 100644
index 0000000..23f870e
--- /dev/null
+++ b/content/weblog/2022-01-25_debugging-in-vim/index.ru.md
@@ -0,0 +1,237 @@
++++
+title = "Как я отлаживаю программы в Vim"
+date = 2022-01-25T19:49:30Z
++++
+
+Мне нравиться использовать отдельные инструменты для разных задач, но также мне
+нравится когда эти инструменты хорошо интегрируются с моими остальными
+инструментами. К сожалению я не видел достаточной информации в интернете насчёт
+возможного процесса отладки программ посредством Vim. Информация, точнее, есть,
+но она разбросана по всему интернету. И так я решил написать о моём процессе
+написания и отладки с Vim.
+
+<!-- more -->
+
+Многие, а может и большинство, IDE уже имеют встроенные функции отладки
+программ. Но также эти IDE не vim, и чаще всего они включаю в себя куча других
+сомнительных функций. И нет, «Vim mode» плагины не считаются, большинство из них
+даже половина функционала Vim'а не включают в себя.
+
+Я обожаю vim (на самом деле использую neovim, кому какая разница), и я считаю
+его лучшим текстовым редактором. Я даже в полном серьёзе считаю что у Vim'а
+лучшее UI/UX из любой программы. Да, он далеко не самая интуитивная программа
+([вставьте мем про выхода из Vim'а](#exit-vim)), но выучить основные азы не так
+сложно как кажется зато как только их выучить сложно будет пользоваться чем-то
+другим. Короче говоря, Vim это не программа а образ жизни.
+
+Проблема заключается в том, что стать продвинутым пользователем вима всё-таки
+занимает немалого времени. А чтобы эффективно разрабатывать программы, не
+достаточно просто напечатать код программы. Так же необходимо быстро
+перемещаться по исходным файлам, быстро исправлять самые банальные ошибки (вроде
+опечатках), свести к минимуму механические задачи (например с помощью
+автозаполнения), и конечно, отладка и профилировка.
+
+К счастью как Vim как и Neovim уже несколько лет предоставляют функционал для
+интегрирования инструментов разработки и отладки с лёгкостью. Так как я
+пользуюсь Neovim, то соответственно некоторые моменты могут отличаться от
+ванильного Vim.
+
+## Инструменты разработки
+
+В старые добрые времена для каждого редактора/IDE отдельно должны были быть
+разработаны плагины или компоненты. То есть, для каждой комбинации редактора и
+языка программирования выполнялся труд по разработке инструмента, что означала
+что далеко не все редакторы и не все языки имели достаточные инструменты для
+разработки и отладки.
+
+К счастью, Мелкомягкие поступили совсем не по Мелкомягкому и вместо того чтобы
+встроить совершенно новую реализацию среды разработки для VSCode, они
+разработали так называемый Language Server Protocol[^1], и с помощью Red Hat и
+других выложили в опен сорс и превратили его в некий стандарт.
+
+Если коротко говоря, то Language Server Protocol (LSP) это просто JSON RPC
+протокол для общения между сервером, который предоставляет функции для
+разработки программ, как например, автозаполнение, статический анализ, переход
+на определение, и т.д., и клиент, то есть, IDE или редактор, который отображает
+результат всех этих действий. Среди редакторов, которые поддерживают LSP,
+находится Vim. В Neovim'е это поддержка даже встроена.
+
+### LSP
+
+Затем чтобы использовать LSP в neovim, необходимо включить плагин и настроить
+LSP сервер(а) ваш(его/их) язык(а/ов). Хорошо то, что настройка этого функционала
+довольно проста, так как есть официальный плагин который уже предоставляет
+настройки по умолчанию для многих LSP разных языков.
+
+Я пользуюсь [vim-plug](https://github.com/junegunn/vim-plug) чтобы управлять
+своими планинами, поэтому я сначала с его помощью добавил плагин
+[lspconfig](https://github.com/neovim/nvim-lspconfig):
+
+```vim
+"...
+ Plug 'neovim/nvim-lspconfig'
+"...
+```
+
+Затем я его настроил под себя, добавляя конфигурации для LSP сервера C, Go,
+Rust, Python, и Javascript, языки, которыми я чаще всего пользуюсь:
+
+```vim
+" LSP
+ set omnifunc=v:lua.vim.lsp.omnifunc
+ lua require('lspconfig').clangd.setup{filetypes = { "c", "cpp", "objc", "objcpp", "ch" }}
+ lua require('lspconfig').gopls.setup{}
+ lua require('lspconfig').pylsp.setup{}
+ lua require('lspconfig').rls.setup{}
+ lua require('lspconfig').tsserver.setup{}
+
+" LSP keybinds
+ nmap <silent> gd <cmd>lua vim.lsp.buf.definition()<CR>
+ nmap <silent> gD <cmd>lua vim.lsp.buf.declaration()<CR>
+ nmap <silent> gK <cmd>lua vim.lsp.buf.hover()<CR>
+ nmap <silent> <leader>n <cmd>lua vim.lsp.buf.rename()<CR>
+ nmap <silent> <leader>b <cmd>lua vim.lsp.buf.formatting()<CR>
+
+" neovim overrides my omnifunc with whatever ccomplete is, so I use this
+ autocmd FileType c,ch,header,cpp setlocal omnifunc=v:lua.vim.lsp.omnifunc
+```
+
+Ну и конечно, затем чтобы пользоваться функционалом, необходимо установить LSP
+сервера. В случае Go и Rust, он уже входит в их официальные тулчейны. Для C
+необходимо установить clang, насколько я знаю GCC не предоставляет имплементацию
+сервера LSP.
+
+Привязка клавиш в моей конфигурации позволяют мне переходить к определению с
+`gd` к декларации с `gD`, открыть всплывающее окно с информации имплементации и
+документирующими комментариями с `gK`, переименовать переменные с `<leader>n`
+(leader в моей конфигурации это пробел), и скормить исходный файл утилиты
+форматирования кода (например, gofmt) с `<leader>b`.
+
+### Другие плагины
+
+LSP предоставляет большинство функций, которые стоит ожидать от IDE, но так же
+есть и другие плагины, которые улучшают процесс редактирования кода. В том
+числе:
+
+```vim
+"...
+ Plug 'ervandew/supertab'
+ Plug 'majutsushi/tagbar'
+ Plug 'tpope/vim-commentary'
+"...
+```
+
+Первый из них, [supertab](https://github.com/ervandew/supertab), делает более
+удобным автозаполнение. По умолчанию автозаполнение `omnifunc` привязано к
+\<C-x\>\<C-o\>, что не очень удобно. Обычно в консольных терминалах и в других
+редакторах клавиша Tab вызывает функцию автозаполнения, что казалось бы
+разумным. Но иногда также есть необходимость вставить символ табуляции вручную.
+Для этого и годиться этот плагин. После нажатия на клавишу Tab, он
+автоматически, в зависимости от контекста, либо вставляет символ табуляции либо
+вызывает автозаполнения.
+
+Далее [tagbar](https://github.com/preservim/tagbar). Данный плагин позволяет
+открывать панель со списком глобальных перемен, определений структур данных, и
+функции в текущем исходном файле. Для его работы требуются ctags.
+
+Наконец [vim-commentary](https://github.com/tpope/vim-commentary), который
+предоставляет возможность легко и быстро закомментировать несколько строк
+одновременно. Не так прямо и полезно как другие плагины, но тем не менее.
+
+## Отладка
+
+Рано или поздно в процессе разработки программного обеспечения вы столкнётесь с
+ошибкой, которая приведёт к неправильно исполнению программы. Можно найти
+проблему вручную выпяливая код и чеща себе голову. Но есть и способ получше.
+Можно открыть отладчик и анализировать программу наблюдая за её исполнение
+пошагово.
+
+Некоторое время, по крайней мере с C и языками поддерживаемые gdb, я просто
+открывал gdb в другом окне с терминалом и оставлял открытым в другом окне Vim с
+исходным кодом. Но появились пару новинок в Vim'е, которые сделали этот процесс
+намного удобнее.
+
+Первая это `terminal`, которая как имя и полагает, является терминальным
+эмулятором внутри самого вима. Если коротко, то оно позволяет открывать новый
+терминал внутри буфера вима. Лично для меня этот функционал сам по себе не очень
+полезный, так как я пользуюсь плиточным оконным менеджером, которые мне и так
+уже предоставляет возможность быстро и удобно перемещаться по окнам. Тем не
+менее, этот плагин делает возможным следующий плагин, который зависит от него.
+
+Звезда нашего шоу — `Termdebug`, плагин, который встроенный как в Vim (версия >=
+8.1) так и в Neovim. То, что он делает это открывать два буфера, один с консолью
+gdb, а второй с выходом отлаживаемой программы. В буфере с консолью пви можно
+традиционным способом пользоваться gdb вводя в неё команды, или через команды
+вима.
+
+Для того, чтобы начать пользоваться Termbug'ом, необходимо сначала подгрузить
+плагин:
+
+```vim
+:packadd termdebug
+```
+
+Затем запускаем его передавая название бинарного файла, который требуется
+отлаживать:
+
+```vim
+:Termdebug <путь к бинарнику>
+```
+
+После запуска появятся два буфера, один с выводом отлаживаемой программы и
+второй с консолью gdb. Оба буфера терминалы. Для того чтобы пользоваться
+терминальными буферами в виме, нужно перейти в режим вставки чтобы печатать в
+терминале. Чтобы выйти из режима вставки необходимо ввести \<C-\\\>\<C-n\>.
+Почему не Esc? А потому, что некоторые терминальные программы пользуются им,
+например, режим vi в bash или zsh. Ну или например другая истанция вима внутриа
+вима, почему бы и нет ¯\\_(ツ)_/¯.
+
+После того, как открыли Termdebug, можно запустить отлаживаемую программу
+традиционным способом с gdb. Или из самого вима с `:Run <аргументы>`. Другие
+полезные команды: `:Break` для того, чтобы вставить точку остановки в текущей
+строке кода, `:Clear` чтобы её удалить, `:Continue` для того чтобы продолжить
+выполнение программы и т.д.
+
+[![Снимок примера отладки программы в Vim](debugging-session.png)](debugging-session.png)
+<figcaption>
+
+Пример отладки программы в Vim.
+</figcaption>
+
+Что делает это замечательным это то, что можно наблюдать за процессом отладки
+прямиком из исходного файла. Не надо постоянно вводить `list` в gdb, можно
+просто переходить по файлам и ставить или удалять точки установки.
+
+Конечно, так как по сути отладка-то происходит в gdb, то правила и те же.
+Например, необходимо компилировать программу с символами для отладки, т.е. с
+флагом `-g`.
+
+## Послесловие
+
+Это только некоторые плагины, которые помогают мне более эффективно писать и
+отлаживать программы в виме. Этот текст не является подробным туториалом
+настройки вима или правильной отладки программ. Им я просто хотел показать как
+можно удобно и легко пользоваться вимом наряду с другими инструментами для
+упрощения разработки и отладки ПО. Существует множество информации в интернете
+насчёт того, как правильно настроить вим, или как отлаживать программы с gdb или
+другими утилитами как valgrind или ASan.
+
+Если хочется узнать больше про LSP в neovim, советую почитать страницу помощи в
+neovim вводя `:help lsp`. Аналогично для Termdebugger `:help Termdebugger`.
+
+Если вам интересно, то моя конфигурация вима доступна по ссылке
+<https://git.yaroslavps.com/configs/vimrice/>
+
+<figcaption id="exit-vim">
+
+![Как выйти из вима](quit-vim.jpg)
+
+Если вы никогда не пользовались вимом, и вы повелись на то, чтобы его открыть,
+после того как прочитали этот текст, и вы не можете выйти из него то, эта
+картинка вам в помощь.
+</figcaption>
+
+[^1]: Не полностью соответствует философии Юникс, но по большей мере да, в том
+ плане что это программа, которая делает одну вещь и делает её хорошо. Да, я
+ тоже в шоке, не ожидал такого от Microsoft. Больше информации по LSP можно
+ прочитать здесь: <https://microsoft.github.io/language-server-protocol/>
diff --git a/content/weblog/2022-01-25_debugging-in-vim/quit-vim.jpg b/content/weblog/2022-01-25_debugging-in-vim/quit-vim.jpg
new file mode 100644
index 0000000..b9025bd
--- /dev/null
+++ b/content/weblog/2022-01-25_debugging-in-vim/quit-vim.jpg
Binary files differ