Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Helix Golf

Helix Golf is a collection of refactoring examples using the Helix Editor, a next generation terminal IDE written in Rust.

Each example is described in-depth, is tested using the latest version of Helix and has a satisfying video demo. Examples aren't just made-up, all of them were created from real situations.

In many cases the Helix Golf examples are much easier to understand and come up with on your own than similar Vim Golf examples, while often being shorter due to multiple cursors being a core editing primitive in Helix.

This makes Helix a perfect swiss army knife text-editor for developers and anyone who seeks to become faster at editing text. It's not just about becoming more productive - it's also really fun!

Demo for each example

All examples are also available in a single code block

You can copy-paste it into Helix and work through it without need for internet!

# snake_case to camelCase

Rename all fields to be camelCase.

## Before

```js
const user_profile = {
  first_name: "John",
  last_name: "Doe",
  birth_date: "1990-05-15",
  email_address: "john_doe@example.com",
  phone_number: "555-123-4567",
  mailing_address: {
    street_name: "Main Street",
    house_number: 123,
    apartment_unit: "4B",
    zip_code: "10001",
    city_name: "New York",
  },
};
```

## After

```js
const userProfile = {
  firstName: "John",
  lastName: "Doe",
  birthDate: "1990-05-15",
  emailAddress: "john_doe@example.com",
  phoneNumber: "555-123-4567",
  mailingAddress: {
    streetName: "Main Street",
    houseNumber: 123,
    apartmentUnit: "4B",
    zipCode: "10001",
    cityName: "New York",
  },
};
```

## Command

```
%s_<enter>5)<alt-,>d~
```

1. `%` selects the entire file
2. `s_<enter>` selects all underscores
3. `5)` rotates the main selection forward 5 times
4. `<alt-,>` removes the primary selection - the lone underscore we want to keep
5. `d` deletes the selections
6. `~` toggles the case

# Text into Array

Join newline-separated data into an array of strings

## Before

```
Hello
This
Is
Helix
```

## After

```js
["Hello", "This", "Is", "Helix"]
```

## Command

```
%<alt-s>ms"<alt-J>i,<esc>xms[
```

1. `%` selects full file
1. `<alt-s>` split selection into multiple selections on newlines
1. `ms"` surrounds each word with quotes
1. `<alt-J>i,` join lines inside selection, select the inserted space, and insert ","s
1. `<esc>xms[` surround by "[]"

# Reverse Golf Example

Switch the "Before" and "After" cases for a Helix Golf example.

## Before

````md
# snake_case to camelCase

Rename all fields to be camelCase.

## Before

```js
const user_profile = {first_name: "John"};
```

## After

```js
const userProfile = {firstName: "John"};
```
````

## After

````md
# camelCase to snake_case

Rename all fields to be snake_case.

## Before

```js
const userProfile = {firstName: "John"};
```

## After

```js
const user_profile = {first_name: "John"};
```
````

## Command

```
ebyxb*Rv""Nn<alt-)>

%s`+j<enter>f;<alt-(>
```

1. `eb` selects the next word and trims whitespace
1. `y` copies the selected word and yanks it into the " (double quote) register
1. `xb` selects the last word in the line
1. `*` sets the current selection as the search pattern
1. `R` replaces the selected word with the copied selection from earlier
1. `v` enters select mode
1. `""` selects the " (double quote) register. Pressing `N` will add a new selection at the previous occurrence of the word saved to the register
1. `n` adds a new selection at the next occurrence of the search pattern assigned earlier
1. `<alt-)>` rotates the contents of the selections forward
1. `%` selects the entire contents of the file
1. `s` brings up a prompt to select sub-selections by a given regex. We type in `` `+j `` for the regex and select all matches with `<enter>` 
1. Since we're still in select mode, typing `f;` moves each cursor to select up until (and including) the next occurrence of a semicolon
1. `<alt-(>` rotates the contents of the selections backwards 

# Object into Array

Convert object into a list of tuples representing the field and the value.

## Before

```js
const palette = {
  apricot: "#f47868",
  lightning: "#ffcd1c",
  delta: "6f44f0",
};
```

## After

```js
const palette = [
  ["apricot", "#f47868"],
  ["lightning", "#ffcd1c"],
  ["delta", "6f44f0"],
];
```

## Command

```
jmr{[mi[s:<enter>

r,bems"vt,ms[
```

1. Go to the line below with `j`, this is because we need to be inside of the object for the next step.
1. `mr{[` replaces the nearest pair of curly braces "\{" with square brackets "["
1. `mi[` selects inside the entire array
1. Use `s` to enter select mode, which searches inside our selection and creates sub-selections based on a pattern
1. Input `:` and then hit `<enter>`, which will place a cursor on every ":" creating many single-width selections
1. `r,` replaces each selection with a ",". Essentially we've replaced each colon with a comma
1. `be` selects the previous word on each line and moves each cursor to the end of each word
1. `ms"` surrounds each word with double quotes to make strings
1. `vt,` selects each line excluding the final comma
1. `ms[` surrounds each individual selection with "[" to turn it into an array

# Export from Rust Module

Each module contains a function, which we want to export.

## Before

```rs
mod generate_demos;
mod mdbook_preprocessor;
mod validate;
```

## After

```rs
mod generate_demos;
mod mdbook_preprocessor;
mod validate;

pub use generate_demos::generate_demos;
pub use mdbook_preprocessor::mdbook_preprocessor;
pub use validate::validate;
```

## Command

```
%yp[<space>

<alt-s>gse

cpub use<esc>leypi::
```

1. `%` select all 3 "mod" statements
1. `yp` duplicate them
1. `[<space>` add a blank line above the 3 duplicated statements
1. `<alt-s>gse` create 3 selections for each "mod" in the duplicated statements
1. `cpub use<esc>` convert each "mod" into "pub use"
1. `ley` copy name of each module
1. `p` duplicate name of each module at the end, since each module contains a function named the same as the module
1. `i::` add a double-colon path separator between them

# Enumerate and Align

Add a new field `rank` to each object, it starts at 1 and increments and align fields to look neat.

## Before

```js
[
  { word: "a", count: 2565 },
  { word: "and", count: 1777 },
  { word: "of", count: 1331 },
  { word: "that", count: 1263 },
  { word: "to", count: 1030 },
  { word: "in", count: 1027 },
  { word: "it", count: 754 },
  { word: "as", count: 730 },
  { word: "was", count: 687 },
  { word: "you", count: 652 },
  { word: "for", count: 630 },
];
```

## After

```js
[
  { rank:  1, word: "a",    count: 2565 },
  { rank:  2, word: "and",  count: 1777 },
  { rank:  3, word: "of",   count: 1331 },
  { rank:  4, word: "that", count: 1263 },
  { rank:  5, word: "to",   count: 1030 },
  { rank:  6, word: "in",   count: 1027 },
  { rank:  7, word: "it",   count:  754 },
  { rank:  8, word: "as",   count:  730 },
  { rank:  9, word: "was",  count:  687 },
  { rank: 10, word: "you",  count:  652 },
  { rank: 11, word: "for",  count:  630 },
];
```

## Command

```
%s\{<enter>a rank: <ctrl-r>

#,<esc>%s |\d+<enter>&
```

1.  `%` selects full file
1.  Use `s` to enter select mode, which searches inside our selection and creates sub-selections based on a pattern
1.  Input `\{` and then hit `<enter>`, which will place a cursor on every "\{", creating many single-width selections
1.  `a ` to go into insert mode after the "\{"
1.  Input `rank: `
1.  `<ctrl-r>` followed by `#` inserts an increasing number for every selection starting with 1
1.  Input `,`
1.  `<esc>` goes back to normal mode
1.  Use `%s` to enter select mode again
1.  Input ` |\d+` which is a regular expression selecting all spaces and numbers, then hit `<enter>`
1.  `&` to align all selections in columns, note that the numbers get right-aligned

# CSV to SQL

## Before

```csv
id 1,Item 1,cost 1,location 1
id 2,Item 2,cost 2,location 2
id 10,Item 10,cost 10,location 10
```

## After

```sql
INSERT INTO `database`.`table` (`id` ,`item` ,`cost` ,`location`) VALUES ('id 1','Item 1','cost 1','Location 1');
INSERT INTO `database`.`table` (`id` ,`item` ,`cost` ,`location`) VALUES ('id 2','Item 2','cost 2','Location 2');
INSERT INTO `database`.`table` (`id` ,`item` ,`cost` ,`location`) VALUES ('id 10','Item 10','cost 10','Location 10');
```

## Command

```
%<alt-s>"yys\d<enter>

dhhbms

``x_ms(IINSERT INTO `

database<esc>

a.`table<esc>la <esc>

AVALUES (<esc>

"yPS,<enter>ms'A;<esc>Fl;~
```

1.  `%` selects full file
1.  `<alt-s>` split selection into multiple selections on newlines
1.  `"yy` yanks the selections into "y" register. We'll need it for later
1.  `s` and then input the pattern `\d` then `<enter>` which creates a selection on all digits
1.  `d` deletes the selections. Essentially we've removed all the digits.
1.  `hh` goes backwards 2 chars, important to make sure we are at the end of each word
1.  Use `b` to select till the beginning of every word, which also nicely selects all the words that there are
1.  `` ms` `` surrounds each word with a backtick
1.  `` ` `` switches all characters to lowercase
1.  `x` selects each line then use `_` to trim the trailing whitespace
1.  `ms(` surrounds each line with parentheses
1.  `I` goes into insert mode at the beginning of each line
1.  Type the following:

    ```
    INSERT INTO `database
    ```

1.  `<esc>` goes back to normal mode
1.  `a` to go into insert mode after the backtick then type:

    ```
    .`table
    ```

1.  `<esc>` goes back into normal mode, then `la` to enter insert mode just before the opening parentheses
1.  Add a space ` ` then `<esc>` to go back into normal mode again
1.  `A` goes into insert mode at the end of each line, now type:

    ```
    VALUES (
    ```

1.  Hit `<esc>` to leave insert mode. Your cursor will be at the closing parenthesis.
1.  `"yP` pastes our previously yanked items from the "y" register
1.  `S,<enter>` splits current selection into multiple selections on each comma
1.  `ms'` surrounds each item with a single quote
1.  `A;` adds a semicolon at the end of each line
1.  `<esc>` goes back to normal mode and `Fl` to place your cursor on the lowercase "l" of each "location"
1.  `;` collapses each selection into a single-width selection
1.  `~` toggles the case for each "l" into "L"

# Function into Class

Convert 3 functions into a class with 3 methods.

## Before

```py
def calculate_area(length, width):
    result = length * width
    return result

def calculate_perimiter(length, width):
    result = 2 * (length + width)
    return result

def calculate_volume(length, width, height):
    result = length * width * height
    return result
```

## After

```py
class Calculator:
    @staticmethod
    def get_area(len, wid):
        return len * wid

    @staticmethod
    def get_perimiter(len, wid):
        return 2 * (len + wid)

    @staticmethod
    def get_volume(len, wid, hei):
        return len * wid * hei
```

## Command

```
%scalculate<enter>cget<esc>

O@staticmethod<esc>jj

vglyx<alt-d>xbRkxx

slength|width|height<enter>

bllled%>O<backspace>

class Calculator:
```

1.  `%` selects the entire file
1.  `s` searches inside the current selection and creates sub-selections based on a pattern. Input `calculate` then hit `<enter>` to make a selection on all instances of the word
1.  `c` then type `get` to change each "calculate" word into a "get"
1.  `<esc>` to go back to normal mode
1.  Use `O` to create an empty line above each cursor, write:

    ```
    @staticmethod
    ```

1.  Hit `<esc>` to go into normal mode.
1. `jj` moves each cursor down two lines
1. `vgl` selects the rest of each line past each cursor
1. `y` copies each selection
1. `x<alt-d>` selects each cursor's line and deletes the line without copying the selection
1. `xb` selects the last word of each cursor's line
1. `R` replaces each selection with the copied selections from earlier
1. `kxx` moves each cursor up one line and selects that line as well as the line below
1.  `s` brings up a prompt to select sub-selections by a given regex. Typing `length|width|height` followed by `<enter>` will select each instance of those 3 words: length, width, and height
1.  Our cursor is currently at the end of each word. Let's go to the beginning with `b`
1.  We want to keep the first 3 characters and discard the rest from each of the parameters. To do this, move to the 4th character with `lll`
1.  Use `e` to select until the end of each word and then `d` to delete it
1.  Select whole file with `%` and indent with `>`
1.  `O` creates a newline above and enters Insert mode, then `<backspace>` to delete an extra tab
1.  Write this:

    ```
    class Calculator:
    ```


snake_case to camelCase

Rename all fields to be camelCase.

Text into Array

Join newline-separated data into an array of strings

Reverse Golf Example

Switch the "Before" and "After" cases for a Helix Golf example.

Object into Array

Convert object into a list of tuples representing the field and the value.

Export from Rust Module

Each module contains a function, which we want to export.

Enumerate and Align

Add a new field rank to each object, it starts at 1 and increments and align fields to look neat.

CSV to SQL

Function into Class

Convert 3 functions into a class with 3 methods.