History of Vim and a guide to its effective use

Note from the translator: this is the first part of the monumental (actually monumental) article about Vim and its capabilities from the developer from Minneapolis and the author of the PostgREST project , Joe begriffs Nelson.



The first part of the article is devoted to getting acquainted with the history of Vim as an editor, and the author talks about a number of interesting facts about the capabilities of Vim. In the second part of the translation, all the chips and life hacks that Joe decided to share with the audience will be concentrated, there the narrative, as such, fades away and there remains only a set of guidelines for action. Since the original text has completely unacceptable dimensions, we divided this story into two approximately equal-sized articles. Today is the first of two publications. Enjoy reading.






This article is based on researching the history of Vim and reading its user guide cover to cover. I hope these notes will help you discover (or rediscover?) The basic functionality of this editor for yourself, as well as allow you to abandon the use of warned vimrc files and use plugins more thoughtfully.







List of references



To go beyond the usual topics, I would recommend getting a paper copy of this manual and a capacious pocket reference. I could not find a printed copy of the user guide for Vim, so in the end I just printed the PDF file that came with the editor using printme1.com. $VIMRUNTIME/doc/usr_??



it come with software in $VIMRUNTIME/doc/usr_??



. As a convenient list of commands I can advise the reference book “Vi and Vim Editors Pocket” .



Content





Story



Birth vi



Vi commands and functions have been around for more than fifty years, starting with the QED editor. Here is his timeline:





If you read the QED and ex manual, you may find some similarities between them. Both editors use similar grammar to indicate and work with line ranges.



Editors such as QED ed and em were designed for print terminals, which for the most part were ordinary electric typewriters with a modem connected to them. Such "full-copier" terminals displayed commands on paper and it was obviously impossible to make any corrections after input. Therefore, the editing process consisted of manually editing user commands on paper, and then re-entering them.



By 1976, video terminals appeared, for example, ADM-3A. An “open mode” was added to the Ex editor, which allowed editing through a video terminal within a single page. A visual mode was added to orient on the lines of the terminal using the cursor. The visual mode was activated by the “vi” command and constantly updated the file displayed on the screen, while maintaining the positioning of the command line at the bottom of the screen. An interesting fact: the h, j, k, l keys on the ADM-3A were marked with arrows that allowed you to move the cursor to vi.



You can learn more about this transition from ed to ex / vi in an interview with Bill Joy . In it, he talks about how he created ex / vi and about some things that eventually disappointed him.



Classic vi is just an alter is ex. Both are represented by the same binary file, which can be run both in ex-mode and vi-mode, depending on the name of the executable file. The legacy of this whole story is that ex / vi “unfolds” when used, it requires almost no system resources and can work in conditions of limited bandwidth. It is also available on most existing systems and is fully described in POSIX.



Vi to vim



Derived from ed, the ex / vi editor was the intellectual property of AT&T. To use vi on platforms other than Unix, people had to write clones that had a different source code base.



Here are some of them:





We will focus on the clone from the center of the list - Vim. Bram Mulenaar wanted to use vi on Amiga and started porting with Atari and developing the vi clone stevie. And he named his version of the port “Vi Imitation”. If you want to learn about this process first hand, then watch his interview for Free Software Magazine.



In version 1.22, Vim was renamed “Vi IMproved”, which indicates the superiority of the copy over the original. Here is a graph of the following major versions with descriptions of some features:







For more information about each version, help smoking is recommended, for example, for vim8. To see the planned updates, as well as a list of known errors, you should turn to todo.txt.



For example, the eighth version included some support for asynchronous jobs due to pressure on the project from NeoVim. The developers of the latter wanted to run debugging and REPL for web scripts right inside the editor.



Generally Vim is superportable. Adapting the entire history of its existence to work on completely different platforms, this editor was forced to stay within the framework of the “easy” culture of coding. Vim runs on OS / 390, Amiga, BeOS and BeBox, Macintosh Classic, Atari MiNT, MS-DOS, OS / 2, QNX, RISC-OS, BSD, Linux, OS X, VMS and MS-Windows. You can rely on Vim anywhere and don't care what equipment you use.



At the end of the original vi path, in 2002, the ex / vi source code was still published under the BSD free software license. Sorcerers are available at ex-vi.sourceforge.net .



But let's get down to business. Before you begin analyzing Vim, it’s useful to know how it organizes and reads its configuration files.



Config hierarchy



I used to mistakenly believe that Vim only gets all its settings and scripts from a .vimrc file. Viewing the repositories of random “dotfiles” can only reinforce this opinion. Quite often, people upload monstrous in essence single .vimrc files whose task is to control every aspect of the editor. These huge configs are sometimes called “vim distros”.



In fact, Vim has a neat structure in which .vimrc is just one of many “entry points”. In fact, you can ask Vim exactly which scripts it loads. To do this, edit some source code for a random project on your machine, download it and then run the command



 :scriptnames
      
      





This list is worth reading. Try to guess what these scripts do and write down the directories in which they are located.



The list was longer than you expected? If you have installed many plugins, then the editor has a lot to do. Verify that it slows down at startup by running the following start.log creation command:



 vim --startuptime start.log name-of-your-file
      
      





Just compare how fast Vim starts from out of the box:



 vim --clean --startuptime clean.log name-of-your-file
      
      





To determine which scripts should be loaded at startup or during buffer loading, you need to check the Vim runtime path. This path is represented by a comma-separated list of directories, each of which contains a common structure. Vim checks these structures in each directory to find its startup scripts. Directories are processed strictly in the order in which they are located in the list.



Check the execution path on your system through this command:



 :set runtimepath
      
      





My system contains the following directories specified by default for runtimepath verification. Not all of them even exist, but Vim will still try to access them and will check the contents if they are still in place:



~/.vim





Home directory, designed for created profiles.



/usr/local/share/vim/vimfiles





System-wide Vim directory, for profiles with system administrator privileges.



/usr/local/share/vim/vim81





Aka $ VIMRUNTIME, for files distributed with Vim.



/usr/local/share/vim/vimfiles/after





In the system-wide Vim directory, there is also the after directory. It is intended to add the "default" system administrator's personal settings.



~/.vim/after





The “after” directory in the home directory. It is necessary so that personal configs do not cancel or overlap with the system-wide or “default” settings.



In general, directories are processed in the same order in which they are written in start.log, an exception is made only for “after”. This one is always at the end of the list and is processed last.



When processing each directory, Vim looks for subfolders in them with specific names. To learn more about this, see help runtimepath. Here is a brief description of those that we will consider further in the text:



plugin /





Here lie the Vim script files that are automatically loaded when editing any type of file. They are also called "global."



autoload /





(Not to be confused with "plugin"). These startup scripts contain functions that are tightened only at the request of other scripts.



ftdetect /





Scripts to determine file types. In their work, they rely on the extension, location, or internal content of the file.



ftplugin /





Scripts that are executed when editing files of a known type.



compiler /





Determines how to run various compilers or lint checks, and how to analyze their output. It can be divided between several ftplugins at once. Compiler is not executed automatically and must be called by a command.



pack /





Container for native Vim 8 packages, the successor to Pathogen-style package management. It has its own packaging system, does not require third-party code to work.



And finally, ~ / .vimrc



is a trap for general editor settings. Used to configure the default settings, which can be assigned to a specific type of file. To view the entire list, you can select .vimrc and run the options command.



3rd party plugins



Plugins are just Vim scripts, for which it’s enough to place them in the correct places in the runtimepath. In general, the installation process is extremely simple: just upload the file (s). The problem is that some plugins are quite difficult to update or remove, because they are scattered in different subdirectories and they clog the execution paths with their scripts. That is, in the end it is difficult to determine which file belongs to which plugin.



To solve this issue, “plugin managers” began to develop. On vim.org there was a registry of plugins at least until 2003 inclusive (if the archive is not lying). However, “plugin managers” as an entity entered fashion only by 2008.



These tools add special directories for plugins to track execution paths and arrange tags by which plugins can be tracked. Most managers also pull up plugin updates from the network.



Below I have built plugin managers according to the chronology of their occurrence. Based on the ranges of release dates of the first and latest versions. If there were no official releases, then I took as a basis the earliest release dates and the last update.





The first thing you need to pay attention to in the list above is the huge variety. The second - each of the tools presented has been “living” for about four years, and then, most likely, goes out of fashion.



The path of least resistance in managing plugins is to simply use the built-in Vim 8 functionality, which does not require pulling up any third-party code. Let's look at how to do it.



First, create two directories inside your runtimepath: opt and start.



 mkdir -p ~/.vim/pack/foobar/{opt,start}
      
      





Pay attention to the placeholder “foobar” (the name can be changed). It fully classifies all packages that fall inside. Most users simply dump all of their plugins into one single category and, in general, this is normal. Choose any name you like; I will continue to use foobar. In theory, you can also create several categories, for example ~/.vim/pack/navigation



and ~/.vim/pack/linting



. Please note that Vim does not recognize duplication between categories and download duplicates twice if they exist.



Packages in "start" are loaded automatically, while packages in "opt" are not loaded until they are from Vim using the command :packadd



. This option is good for rarely used packages and is supported by Vim out of the box, without having to run scripts. Note that :packadd



no counterpart for unloading packages.



To review this example, we will add the ctrlp fuzzy search plugin to opt. Download and unzip its latest version at:



 curl -L https://github.com/kien/ctrlp.vim/archive/1.79.tar.gz \ | tar zx -C ~/.vim/pack/foobar/opt
      
      





This command will create the ~ / .vim / pack / foobar / opt / ctrlp.vim-1.79



ready-to-use package. Go back to vim and create the helptags index for the new package:



 :helptags ~/.vim/pack/foobar/opt/ctrlp.vim-1.79/doc
      
      





This command will create a file called “tags” in the folder with the package sorts, which make themes available for viewing in the Vim internal system. Alternative way: run helptags ALL after downloading the package, and the command will take care of all the files and their execution paths.

When you want to use a package, just download it and remember that in this case termination works using tabs, so you do not need to enter the full name:



 :packadd ctrlp.vim-1.79
      
      





The base directory of Packadd lies in the runtimepath, which allows it to use its plugin and ftdetect scripts. After loading ctrlp, you can use the CTRL-P command to open the file search by partial match.



Some people keep track of their ~ / .vim directory and use git to control the version of each package. For my part, I just unpack packages from tar archives and track them manually through the repository. If you use sufficiently mature packages that do not require frequent updates, as well as scripts, then they are small enough and do not clutter up the git history.



Backups and rollbacks of versions



Depending on your user preferences, Vim can protect you from four possible causes of data loss:



  1. Crash while editing (between saves). Vim can protect against this by periodically saving changes to the page file.
  2. Protection against editing the same file with two Vim instances, protection against overwriting changes made through one or several instances. This is also done through the swap file.
  3. Crash during the save process itself after changing the final file, but until the new content is completely written. Vim can protect you from this with the writebackup function. To do this, he creates in the process of saving a new file, which subsequently replaces the original, if everything went smoothly. The replacement method is determined by the backupcopy setting.
  4. Saving the new contents of the file provided that the original is restored. Vim allows you to back up a file after making changes.


But before you start exploring these smart settings, how about a couple of jokes? Here are some sample comments from vimrc files on GitHub:



“Do not create a page file. Manage everything through version control. ”

“Backups for exiles. Use version control. ”

“Only version control!” Only hardcore! ”

“We live in a world of version control, so swaps and backups are in the trash.”

“Why do you need backup files if version control is enough.”

"I have never used Vim backup files ... Use version control."

“Most things can be found through version control.”

"Turn off file backups, because you still use the version control system;)".

"And version control came, and Git saved us."

“Disable swap files and backup system. Always use version control! ALWAYS!"

“I don’t need a backup, because I work with version control.”



The irony is that the comments above reflect only an understanding of the fourth and, in part, third type of failure. If you refuse the swap file and backup, you will lose protection in the case described in paragraphs 1 and 2.



Here is an example configuration that I recommend for safe operation:



 " Protect changes between writes. Default values of " updatecount (200 keystrokes) and updatetime " (4 seconds) are fine set swapfile set directory^=~/.vim/swap// " protect against crash-during-write set writebackup " but do not persist backup after successful write set nobackup " use rename-and-write-new method whenever safe set backupcopy=auto " patch required to honor double slash at end if has("patch-8.1.0251") " consolidate the writebackups -- not a big " deal either way, since they usually get deleted set backupdir^=~/.vim/backup// end " persist the undo tree for each file set undofile set undodir^=~/.vim/undo//
      
      





These settings include backing up for incomplete recordings, but do not save files after the operation is completed successfully, because we have version control, the best version control, blah blah blah, etc. etc. Please note that you may need mkdir ~ / .vim / {swap, undodir, backup}, otherwise Vim will access the next readable folder. You will also probably need to run the chmod command on the target folders so that their contents are private, as the swap files and backup history may contain sensitive information.



It is worth noting that the peculiarity of our config paths is that they always close with a slash. This spelling allows the function to eliminate the possible ambiguity in the paths of the paging and backup files for files with the same names, which are in different directories. For example, the swap file for / foo / bar will be saved in ~ / .vim / swap /% foo% bar.swp (I escaped slashes with percent signs). There was a bug in the recent Vim patch that prevented the slash from being taken into account for backupdir, so protection against it is shown above.



Our Vim also saves rollback history for each file, so that you can restore the desired version even after exiting edit mode. Although such a function may seem redundant against the background of the swap file we already have, rollback history is an additional border of protection during file recording.



When we talk about rollbacks, it is worth remembering that Vim supports a complete tree of file editing history. This means that you can make a change, roll back it, and then repeat the same changes again, and all this will be three different recovery points. The time and extent of the changes made can be checked using the undolist command, but it is problematic to get the tree out of it. : 5 , . , — , undotree — .



. . : . , .



: , ,vim . nowritebackup, , . , Vim , . backupskip .



«patchmode» Vim . , . , tar-, , git. set patchmod = .orig foo- foo.orig.



Include path



(include) . Vim path, include, suffixesadd, includeexpr. (. help include-search) — ctags .



. , . , help include



.



, [i



, , [d



. gf



Vim . :find, **/*



, . , .. , .



, . ( ) CTRL-D. .



 " fuzzy-find lite nmap <Leader><space> :e ./**/
      
      





: path (headers) . , : checkpath, , . C checkpath. , , . , checkpath , .



«., / Usr / include ,,»



. , — /usr/include, . , :help file-searching



.



ftplugin ( ) , . : ./src/include ./include.



 setlocal path=.,,*/include/**3,./*/include/**3 setlocal path+=/usr/include
      
      





«**3»



— . , . , .



, , :checkpath , . , , .



: :he [, :he gf, :he :find



.






.



All Articles