Skip to the content.

Chapter 8 - Multiple Cursors

Back to outline

And now, introducing the feature you have all been waiting for, the one and only:Multiple Cursors!

This is probably the most powerful, and useful, feature any text editor can have. Sadly enough, it might also be one of the most underused features. Let’s take a moment to compose ourselves, make sure we’re wide awake for this chapter, and dive into the wonderful world of multi-line editing.

Toggle Column Mode Mac + shift + 8

Part 1

For starters, let’s introduce you to Column Mode. Let’s open Chapter8. The output variable contains a long string concatenation, but there are a few problems with it:

You could put your cursor at the beginning of the second line, type a +, and then press Mac and Mac + , and type a + again. Now you could repeat that process for every line, but there’s an easier way.

Since all the strings are lined up perfectly, wouldn’t it be easier if we could first put a bunch of cursors in front of every line, and then just type +? Let’s try to do just that.

First position your cursor at the beginning of the second string ("one hell of a"). While watching the bottom right of your screen press Mac + shift + 8 once. You should see the word Column appear next to UTF-8. This means you have just toggled on Column Mode.

Now, hold down Macshift and press Mac until you’ve reached the last string ("of column mode"). There should be a cursor blinking at the beginning of every line. It might look like one giant cursor, but it is in fact a bunch of them.

Now simply type a + and be amazed.

Exit out of your multi-cursors by pressing MacEscape. Exit out of Column Mode by pressing Mac + shift + 8 again. The word Column should no longer appear in the bottom right, indicating you have indeed exited column select mode.

Part 2

Let’s undo our changes by pressing Mac + Z and take a different approach. Notice how using Mac + Z once puts the multiple cursors back.

Now, what we really want is a + at the end of every string, and to add a space inside all the strings. Here is how you could do that.

Instead of putting your cursor at the beginning of the second line, put it at the beginning of the first line ("This sure is").

Toggle Column Mode again with Mac + shift + 8, and select all the lines again by repeatedly pressing Mac until you’ve reached the second to last string.

Now press Mac + . Notice how the cursors are all at different ending positions.

First let’s add the spaces so our strings aren’t pressed together as much. Move your cursor inside of the string by pressing Mac once. Then type a Macspace.

Then press MacEnd again and type a Mac+. MacEscape out of the multi-cursor and disable Column Mode by pressing Mac + shift + 8.

This is a great feature when all the lines you want to edit are directly underneath each other. However, that won’t always be the case. Let’s take a look at how we can cope with those situations.

Mac + g, Mac + shift + g and Mac + + g

In Chapter8 there are two methods that need some fixing. They both tried to use a StringBuilder but seemed to have forgotten to use the append() method. We can’t use Column Mode because the same mistake is repeated in a different method and there are lines in between that we don’t want to put a cursor at.

We can, however, use Mac⌃ ctrl + g to add a cursor to a Find buffer (MacF3 and Mac⌃ ctrl + F3).
Take a moment to think about what selection you would want to Find in that class. First, try and see what would be included by pressing Mac + F3 on the following selections: ", ., .".

[!TIP] Spoiler:

So let’s select the first ." at 21:17 and press Mac⌃ ctrl + g once and see what happens. Now repeat Mac⌃ ctrl + g until you’ve selected all of the occurrences. You’ll notice that the last occurrence is working code, and we don’t want to change that last one. So press Mac⌃ ctrl + shift + g to undo that last add to cursor selection.

Then let’s fix the code by typing append after the .. Don’t exit out of your multi-cursor just yet.

Remember how in Chapter 3 we learned about IntelliJ’s Wrapping feature? Maybe you also recall how we said that it was gonna shine in this chapter?

If you haven’t already, enable Wrapping with Mac + shift + A, smart braces, enter.

From the multi-cursors positioned after the append you just typed, press Macshift + «kbd>⌘</kbd> + to select all the strings, and then press (.

As an alternative to repeatedly pressing Mac⌃ ctrl + g, and if you’re 100% sure that you won’t include too much, you can also press Mac + ⌃ ctrl + g and add all occurrences to your cursors in one go.

Undo Mac + z your corrections and try it out.

Notice how Mac⌃ ctrl + shift + g still deselects the last occurrence. This is because Mac + ⌃ ctrl + g is merely a repeated Mac⌃ ctrl + g.

NOTE:
Using this key combination often is also a great way to train your manual dexterity.

Various use cases

Now that we’ve seen the basics of creating and using multiple cursors, let’s try to apply it to some everyday tasks. We will see how using multiple selections can make your developer life so much easier.

Creating a TestBuilder

In IntelliJ, you can create a Unit Test for a class by pressing Mac + shift + t from the class you’re currently editing.

We will now use this to our advantage while creating a TestBuilder. Open PersonTO with Mac + o, and press Mac + shift + t.

Overwrite the class name from PersonTOTest to PersonTOTestBuilder and press MacEnter.

You might want to get rid of unnecessary org.junit.Assert.* imports by pressing Mac⌃ ctrl + + o to Organize Imports.

Go back Mac + [ to the PersonTO, and copy all private fields over to the PersonTOTestBuilder.

Create an empty constructor for the TestBuilder with Mac + n. Press Mac and ctrl + enter to choose empty constructor from the generation menu.

Create a build() method that returns a PersonTO.

Now, while still inside the PersonTOTestBuilder, generate setters for all the private fields we just copied from PersonTO: Press Mac + n, select Setters, then press Macshift + + to select all the fields, and press Macctrl + Enter.

Using Enter would also work, but it is advisable to use Macctrl + Enter when in a separate window, to press the highlighted button, and perform the Default action.

TIP:
Commit this sequence to muscle memory, you will get good mileage from it.

Now we’ve got a bunch of setters in our builder… That’s great, but we also want the methods to be chainable.

Select the “void set” part of the first setter, and press Mac + ⌃ ctrl + g. Type PersonTOTestBuilder (because we want a Fluent API, using chainable interfaces).

Now we’ve got some options with our method names. We either want all of our configurable methods to have the with prefix, or you want them lowercased.

We can lowercase all of our methods by selecting the first letter: from your multi-cursors position press Macshift + . Then press Mac + shift + u to toggle lower or upper case.

Now the only thing we need to do is to change the return statement to: return this;. Let’s press Mac, then press Macshift + enter, and type return this;

There you go! We managed to create a TestBuilder in less than a minute of work. Time to be pleased with ourselves and fetch a hot beverage.

Testing Enum Lists

Open Status.java, and use Mac⌃ ctrl + g on NOT_REALLY until you’ve got cursors on all the enums with that status. Now try to select the Statuses themselves.

TIP:
You might have to disable CamelHumps with Mac + a to help with the selection.

Copy (Mac + c) these. Now navigate back to StatusTest.java. Before you paste, enable Column Mode (Mac + shift + 8), make sure there’s a bunch of empty lines, and paste your buffered lines to their destination. By using Column Mode, we ensure our multiple cursors remain active and usable after pasting.

With our multi-cursors still there, put a , behind every copied enum value, and press Mac⌃ ctrl + shift + j to join all the lines.

Now: complete the yaReallyStatuses_ContainOnlyDoneAndDunno test on your own.

TIP:
Mac + N is context sensitive, meaning IntelliJ will know what you want because you’re in a Unit Test.

Making csv lists from XML

Here’s an excerpt of an XML file containing a bunch of people from DC’s Batman universe.

<?xml version="1.0" encoding="UTF-8"?>
<Persons>
    <Person>
        <FirstName>Bruce</FirstName>
        <LastName>Wayne</LastName>
        <Age>24</Age>
        <SecretIdentity>Batman</SecretIdentity>
    </Person>
    <Person>
        <FirstName>Pamela Lillian</FirstName>
        <LastName>Isley</LastName>
        <Age>26</Age>
        <SecretIdentity>Poison Ivy</SecretIdentity>
    </Person>
    <Person>
        <FirstName>Edward</FirstName>
        <LastName>Nigma</LastName>
        <Age>41</Age>
        <SecretIdentity>The Riddler</SecretIdentity>
    </Person>
</Persons>

So let’s open (Mac + O) Batman.xml, and navigate to the directory where it’s at with Mac + 1.

Create a new file with Mac + n and call it persons.csv.

Copy the contents of Batman.xml into persons.csv. We can already delete the first line with Mac + backspace.

We know that every </ denotes the end of one field, but if we were to use Mac + ⌃ ctrl + g on that, we would also include the </Person> tags.

These tags though, denote the end of one line, so let’s first get rid of those and replace them with simple new lines. This means we can simply get rid of the start tag <Person> with Mac + backspace.

Your file should now only contain items like this one:


<FirstName>Bruce</FirstName>
<LastName>Wayne</LastName>
<Age>24</Age>
<SecretIdentity>Batman</SecretIdentity>

Select all the closing tags by selecting </ and Mac + ⌃ ctrl + g, and replace them by a ,.

Your file should now only contain items that look like this:


<FirstName>Bruce,
    <LastName>Wayne,
        <Age>24,
            <SecretIdentity>Batman,

We will now get rid of the opening tags, so we end up with a CSV-formatted file.

If you want to retain the tag names as a CSV header line you can Mac⌃ ctrl + g on the opening angular brackets (<) and Mac⌥ Opt + to select all tag names.

Paste them at the top ( Mac + ) while in Column Mode to retain the multi-cursors, at the end (Mac + ) of the line put a , and press Mac⌃ ctrl + shift + j. The j indicating we wish to join lines together.

Then select all the opening tags by selecting < and pressing Mac + ⌃ ctrl + g.

Expand selection with Mac⌥ Opt + , delete the tags, and join the lines together (Mac⌃ ctrl + shift + j). Now remove the last , at the end of the line. You can then still get rid of excess new lines by pressing Mac and either Mac⌃ ctrl + shift + j or <Mackbd>⌘</kbd> + backspace delete line.

And that’s it.


Next Chapter

Back to outline