The Jump List


So far we have looked at various ways to navigate within buffers, then marks introduced the concept of marking locations in buffers and files to allow us to quickly jump to them. We also looked at searching and how it can help us quickly jump to specific content based on patterns.

As we navigate through projects, it can get a bit difficult to keep track of where we have been and how to get there. To help, Neovim maintains a list of "breadcrumbs" called "the jump list", which keeps track of the cursor locations prior to each jump, allowing you to easily return to previous locations.

Lets walk through an example to see how it works. Starting from the following buffer, first note that the status bar indicates that the cursor is located at 1:1. We will come back to this in a moment. Next, let's execute a search for opening HTML tags, then view the jump list by executing :jumps.

Initial Conditions
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
COMMANDTop1:1
/<
Execute the Search
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL30%3:1
 
View the Jump List
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL30%3:1
 
:jumps jump line  col file/text   1     1    0 <!DOCTYPE html>>

The jump list, shown in step 2, contains several columns that provide some useful information. The left-most column contains a number associated with each jump. Since this is the first jump, it has the number 1. The second and third columns correspond to the line and column from which we jumped. In this case we started from the top-left corner of the buffer, which we saw was position 1:1. We can see that the line is 1, and the column is... 0?

Similar to what we saw in setting marks, while the position indicated in the status line is (1,1)-indexed, the output of :jumps is (1,0)-indexed, meaning that rows start at 1, while columns start at 0, so the columns reported by :jumps are always 1 less than the cursor position when the jump was made.

Finally, in order to help us more quickly identify the position of each jump in the list, the fourth column of each line in the jump list provides a hint regarding the position of the jump. Jump locations that are located in the current buffer show the content of that line (or an excerpt of it), while those that are located in other files show that filename. In this example, we just jumped from the line containing the <!DOCTYPE> tag, so the first entry in the jump list refers to that line.

Finally, the jump list uses a > marker to indicate our current position position in the jump list. For now, the > is located at the bottom of the list, indicating that we are current at the top of the list. We will discuss this in more detail in the next section.

With this background, let's note that the cursor is currently located at 3:1, then repeat the search using n, then check the jump list:

Repeat the Searchn
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL50%5:5
 
View the Jump List
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL50%5:5
 
:jumps jump line  col file/text   2     1    0 <!DOCTYPE html>   1     3    0 <html lang="en">>

Repeating the search moved the cursor to the next HTML tag, and added a new line to the jump list (shown in step 4). We just jumped from the <html> tag, so the jump #1 refers to this line, while the previous jump is not jump #2. Finally, the > marker still indicates that we are at the top of the list.

To show the next important thing to understand about the jump list, let's repeat the search a few more times, checking the jump list after each jump:

Repeat the searchn
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL60%6:9
 
View the Jump List
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL60%6:9
 
:jumps jump line  col file/text   3     1    0 <!DOCTYPE html>   2     3    0 <html lang="en">   1     5    4 <head>>
Repeat the search againn
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL70%7:9
 
View the Jump List
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL70%7:9
 
:jumps jump line  col file/text   4     1    0 <!DOCTYPE html>   3     3    0 <html lang="en">   2     5    4 <head>   1     6    8 <meta charset="utf-8">>

As expected, the most recent jump is now 1, while the number of each previous jump has incremented. Now, let's repeat the search backwards, using N:

Repeat the search in reverseN
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL60%6:9
 
View the Jump List
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL60%6:9
 
:jumps jump line  col file/text   5     1    0 <!DOCTYPE html>   4     3    0 <html lang="en">   3     5    4 <head>   2     6    8 <meta charset="utf-8">   1     7    8 <title>Title</title>>

As expected this jump add one more jump to the list. However, then next jump is a bit more interesting:

Repeat the search in reverse againN
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL50%5:5
 
View the Jump List
<!DOCTYPE·html>
 
<html·lang="en">
 
····<head>
········<meta·charset="utf-8">
········<title>Title</title>
········<meta·name="description"·content="Description">
········<meta·name="author"·content="Author">
NORMAL50%5:5
 
:jumps jump line  col file/text   5     1    0 <!DOCTYPE html>   4     3    0 <html lang="en">   3     5    4 <head>   2     7    8 <title>Title</title>   1     6    8 <meta charset="utf-8">>

Now, comparing the jumps lists of steps 10 and 12 we see that the original jump associated with the <meta> tag has disappeared. What happened? The jump list is not a simple linear history of jumps, like a browser history. Each time a jump is added to the list, any other jumps associated with that line are removed. This prioritizes locations that we jump to more often by keeping them towards the top of the list, allowing us to traverse back to them more quickly. This also keeps the list pruned so that we can more easily traverse back to less-common locations.

With this background, let's now look at how to traverse the jump list.