Welcome to tui.ninja!


expand_more
Sometimes it can be handy to get a quick diff of the changes that have been made to the current buffer since the previous save. This can be achieved with a simple command-line mode command. To demonstrate, let's start with the following buffer: Initial Conditions a = [ "one", "two", "three", "five", ] COMMAND Top 1:1 :%s/two/changed Now lets edit the buffer. To keep it simple we will make a single edit, changing "two" to "changed": Edit the Buffer a = [ "one", " changed", "three", "five", ] NORMAL 43% 3:5 Now, we can generate a simple diff with the command: :write !diff % - Let's review what this does. To start, this uses the :write command with the following call signature: :w[rite] !{cmd} Which passes the entire contents of the current buffer to the specified command via stdin . In this example we will use the diff shell command, which has the call signature: diff file1 file2 where our command defines file1 and file2 as: file1 = % , which contains the filename of the current file, and file2 = - , which tells diff to read stdin So, putting this all together, we pass the current buffer contents to the diff command, and generate the diff between the saved version of the current file ( % ) and the current buffer contents. Finally, the diff is passed back to Neovim: Generate the Diff a = [ "one", " changed ", "three", "five", ] NORMAL 43% 3:5 :write !diff % - 3c3 <     "two", --- >     "changed", shell returned 1 The output window shows that the line containing "two" has been changed to "changed". diff also returns a status code if 1 , meaning that the two files were different. This is definitely not the prettiest diff in the world, but is useful when a quick diff is required. Take a look at: diff --help to see what options are available to suit the output to your needs. For example, by leveraging diff 's options one can format the same output as a side-by-side diff: :write !diff -yt -W 60 % - Alternate Output a = [ "one", " changed ", "three", "five", ] NORMAL 43% 3:5 :write !diff -yt -W 60 % - a = [                           a = [ "one",                          "one", "two",                   |      "changed", "three",                        "three", "five",                         "five", ]                               ] shell returned 1
Reorganizing lines in a buffer is a very common task. While a yank and paste sequence could be used for each line, there is a better way. The following keymaps allow a line or group of lines to be easily moved up or down using a single keystroke: -- single-line vim . keymap . set ( "n" , "<A-j>" , ":move .+1<CR>==" ) vim . keymap . set ( "n" , "<A-k>" , ":move .-2<CR>==" ) -- multi-line vim . keymap . set ( "v" , "<A-j>" , ":move '>+1<CR>gv=gv" ) vim . keymap . set ( "v" , "<A-k>" , ":move '<-2<CR>gv=gv" ) To see how they work, consider the following buffer: Initial Conditions a = [ "one", "three", "two", "four", "five", ] NORMAL Top 1:1 Note that the words are out of order, and we would like to fix that. We start by moving the cursor to the line that we want to move (i.e. the "target" line): Move to Target Line 2j a = [ "one", "three", "two", "four", "five", ] NORMAL 38% 3:1 With this keymap, hitting A-J allows us to easily move the currently down one position, swapping its position with the line below it: Move Current Line <A-j> a = [ "one", "two", "three", "four", "five", ] NORMAL 50% 4:1 To get a better idea about what happened, consider the command that executed when we hit A-J : :move .+1<CR>== The :move command has a call signature: :m[ove] {address} and moves the current line (or selected lines) to the line below the specified address. In this case, the specified address is .+1 , which we learned in the ranges chapter means "the line below the current line". The carriage return causes the preceding command to execute, which is follows by == , which formats (indents) the line after it is moved. Let's see how this works with a visual selection . First, let's move the cursor so that the selection spans three lines: Select Multiple Lines v 2j a = [ "one", "two", "three", "four", "five", ] VISUAL 75% 6:1 Note that although the selection only touches the third line, the entire line is included in the block of lines to move. Now, move these lines up: Move Multiple Lines <A-k> a = [ "one", "three", "four", "five", "two", ] VISUAL 62% 5:1 3 lines indented The selected lines have each move up one line, and the line containing "two" (which has previously been above the selection) is now located below the selection.
It is a common task to search and replace all occurrences of a word within the current buffer. For example, given the following buffer : Initial Conditions B eautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. Sparse is better than dense. Readability counts. COMMAND Top 1:1 :%s/is/is way/ Suppose one wants to change all occurrences of is better to is way better . The general template for searching and replacing is: :[range]s/{pattern}/{replacement}/[flags] where Template Value Description : Puts Vim into Command Mode [range] % Applies this command to the entire file s/ Indicates that this is a search and replace operation {pattern}/ is Specifies the pattern to search for {replacement}/ is way Specifies the text to replace the search pattern with. [flags] No flags are specified. Putting this all together and executing the command: Title B eautiful is way better than ugly. Explicit is way better than implicit. Simple is way better than complex. Complex is way better than complicated. Flat is way better than nested. S parse is way better than dense. Readability counts. NORMAL 75% 6:1 6 substitutions on 6 lines As expected, each occurrence of is has been replaced with is way . Writing patterns can sometimes require a bit of trial and error, if the final text is not as expected, simply hit u to return to the original: Title u B eautiful is better than ugly. Explicit is better than implicit. Simple is better than complex. Complex is better than complicated. Flat is better than nested. S parse is better than dense. Readability counts. NORMAL Top 1:1 6 changes; before #1 0 seconds ago