Unnamed repository; edit this file 'description' to name the repository.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function_clause
  pattern: (arguments (_)? @parameter.inside)
  body: (_) @function.inside) @function.around

(anonymous_function
  (stab_clause body: (_) @function.inside)) @function.around

(comment (comment_content) @comment.inside) @comment.around

; EUnit test names.
; (CommonTest cases are not recognizable by syntax alone.)
((function_clause
   name: (atom) @_name
   pattern: (arguments (_)? @parameter.inside)
   body: (_) @test.inside) @test.around
 (#match? @_name "_test$"))
ody h3 { font-size: 18px; color: #CCCAC2; } .markdown-body h4 { font-size: 16px; color: #CCCAC2; } .markdown-body h5 { font-size: 14px; color: #CCCAC2; } .markdown-body h6 { color: #CCCAC2; font-size: 14px; } .markdown-body p, .markdown-body blockquote, .markdown-body ul, .markdown-body ol, .markdown-body dl, .markdown-body table, .markdown-body pre { margin: 15px 0; } .markdown-body hr { border: 2px solid #8A9199; } .markdown-body>h2:first-child, .markdown-body>h1:first-child, .markdown-body>h1:first-child+h2, .markdown-body>h3:first-child, .markdown-body>h4:first-child, .markdown-body>h5:first-child, .markdown-body>h6:first-child { margin-top: 0; padding-top: 0; } .markdown-body a:first-child h1, .markdown-body a:first-child h2, .markdown-body a:first-child h3, .markdown-body a:first-child h4, .markdown-body a:first-child h5, .markdown-body a:first-child h6 { margin-top: 0; padding-top: 0; } .markdown-body h1+p, .markdown-body h2+p, .markdown-body h3+p, .markdown-body h4+p, .markdown-body h5+p, .markdown-body h6+p { margin-top: 0; } .markdown-body li p.first { display: inline-block; } .markdown-body ul, .markdown-body ol { padding-left: 30px; } .markdown-body ul.no-list, .markdown-body ol.no-list { list-style-type: none; padding: 0; } .markdown-body ul li>:first-child, .markdown-body ul li ul:first-of-type, .markdown-body ul li ol:first-of-type, .markdown-body ol li>:first-child, .markdown-body ol li ul:first-of-type, .markdown-body ol li ol:first-of-type { margin-top: 0px; } .markdown-body ul li p:last-of-type, .markdown-body ol li p:last-of-type { margin-bottom: 0; } .markdown-body ul ul, .markdown-body ul ol, .markdown-body ol ol, .markdown-body ol ul { margin-bottom: 0; } .markdown-body dl { padding: 0; } .markdown-body dl dt { font-size: 14px; font-weight: bold; font-style: italic; padding: 0; margin: 15px 0 5px; } .markdown-body dl dt:first-child { padding: 0; } .markdown-body dl dt>:first-child { margin-top: 0px; } .markdown-body dl dt>:last-child { margin-bottom: 0px; } .markdown-body dl dd { margin: 0 0 15px; padding: 0 15px; } .markdown-body dl dd>:first-child { margin-top: 0px; } .markdown-body dl dd>:last-child { margin-bottom: 0px; } .markdown-body blockquote { border-left: 4px solid #FFAD66; padding: 0 15px; color: #B8CFE6; } .markdown-body blockquote>:first-child { margin-top: 0px; } .markdown-body blockquote>:last-child { margin-bottom: 0px; } .markdown-body table th { font-weight: bold; } .markdown-body table th, .markdown-body table td { border: 1px solid #8A9199; padding: 6px 13px; } .markdown-body table tr { border-top: 1px solid #8A9199; background-color: #242936; } .markdown-body table tr:nth-child(2n) { background-color: #1A1F29; } .markdown-body img { max-width: 100%; -moz-box-sizing: border-box; box-sizing: border-box; } .markdown-body span.frame { display: block; overflow: hidden; } .markdown-body span.frame>span { border: 1px solid #8A9199; display: block; float: left; overflow: hidden; margin: 13px 0 0; padding: 7px; width: auto; } .markdown-body span.frame span img { display: block; float: left; } .markdown-body span.frame span span { clear: both; color: #CCCAC2; display: block; padding: 5px 0 0; } .markdown-body span.align-center { display: block; overflow: hidden; clear: both; } .markdown-body span.align-center>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: center; } .markdown-body span.align-center span img { margin: 0 auto; text-align: center; } .markdown-body span.align-right { display: block; overflow: hidden; clear: both; } .markdown-body span.align-right>span { display: block; overflow: hidden; margin: 13px 0 0; text-align: right; } .markdown-body span.align-right span img { margin: 0; text-align: right; } .markdown-body span.float-left { display: block; margin-right: 13px; overflow: hidden; float: left; } .markdown-body span.float-left span { margin: 13px 0 0; } .markdown-body span.float-right { display: block; margin-left: 13px; overflow: hidden; float: right; } .markdown-body span.float-right>span { display: block; overflow: hidden; margin: 13px auto 0; text-align: right; } .markdown-body code, .markdown-body tt { margin: 0 2px; padding: 0px 5px; border: 1px solid #8A9199; background-color: #282E3B; border-radius: 3px; color: #CCCAC2; } .markdown-body code { white-space: nowrap; } .markdown-body pre>code { margin: 0; padding: 0; white-space: pre; border: none; background: transparent; } .markdown-body .highlight pre, .markdown-body pre { background-color: #282E3B; border: 1px solid #8A9199; font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-radius: 3px; } .markdown-body pre code, .markdown-body pre tt { margin: 0; padding: 0; background-color: transparent; border: none; } pre { line-height: 125%; } td.linenos .normal { color: #8a919966; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: #8a919966; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #363C48 } .highlight .c { color: #6E7C8E } /* Comment */ .highlight .err { color: #FF6666 } /* Error */ .highlight .g { color: #CCCAC2 } /* Generic */ .highlight .k { color: #FFAD66 } /* Keyword */ .highlight .o { color: #F29E74 } /* Operator */ .highlight .ch { color: #6E7C8E } /* Comment.Hashbang */ .highlight .cm { color: #6E7C8E; font-style: italic } /* Comment.Multiline */ .highlight .cp { color: #FFAD66 } /* Comment.Preproc */ .highlight .cpf { color: #D5FF80 } /* Comment.PreprocFile */ .highlight .c1 { color: #6E7C8E; font-style: italic } /* Comment.Single */ .highlight .cs { color: #6E7C8E } /* Comment.Special */ .highlight .gd { color: #F27983 } /* Generic.Deleted */ .highlight .ge { color: #FFD173; font-style: italic } /* Generic.Emph */ .highlight .gr { color: #FF6666 } /* Generic.Error */ .highlight .gh { color: #FFD173; font-weight: bold } /* Generic.Heading */ .highlight .gi { color: #87D96C } /* Generic.Inserted */ .highlight .go { color: #D5FF80 } /* Generic.Output */ .highlight .gp { color: #F29E74 } /* Generic.Prompt */ .highlight .gs { color: #FFD173; font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #CCCAC2 } /* Generic.Subheading */ .highlight .gt { color: #FF6666 } /* Generic.Traceback */ .highlight .kc { color: #DFBFFF } /* Keyword.Constant */ .highlight .kd { color: #FFCC66 } /* Keyword.Declaration */ .highlight .kn { color: #FFAD66 } /* Keyword.Namespace */ .highlight .kp { color: #FFAD66 } /* Keyword.Pseudo */ .highlight .kr { color: #FFAD66 } /* Keyword.Reserved */ .highlight .kt { color: #73D0FF } /* Keyword.Type */ .highlight .m { color: #DFBFFF } /* Literal.Number */ .highlight .s { color: #D5FF80 } /* Literal.String */ .highlight .na { color: #FFD173 } /* Name.Attribute */ .highlight .nb { color: #F28779 } /* Name.Builtin */ .highlight .nc { color: #5CCFE6 } /* Name.Class */ .highlight .no { color: #DFBFFF } /* Name.Constant */ .highlight .nd { color: #FFDFB3 } /* Name.Decorator */ .highlight .nf { color: #FFD173 } /* Name.Function */ .highlight .nt { color: #5CCFE6 } /* Name.Tag */ .highlight .ow { color: #F29E74 } /* Operator.Word */ .highlight .w { color: #CCCAC2 } /* Text.Whitespace */ .highlight .mb { color: #DFBFFF } /* Literal.Number.Bin */ .highlight .mf { color: #DFBFFF } /* Literal.Number.Float */ .highlight .mh { color: #DFBFFF } /* Literal.Number.Hex */ .highlight .mi { color: #DFBFFF } /* Literal.Number.Integer */ .highlight .mo { color: #DFBFFF } /* Literal.Number.Oct */ .highlight .sa { color: #D5FF80 } /* Literal.String.Affix */ .highlight .sb { color: #F29E74 } /* Literal.String.Backtick */ .highlight .sc { color: #D5FF80 } /* Literal.String.Char */ .highlight .dl { color: #D5FF80 } /* Literal.String.Delimiter */ .highlight .sd { color: #95E6CB; font-style: italic } /* Literal.String.Doc */ .highlight .s2 { color: #D5FF80 } /* Literal.String.Double */ .highlight .se { color: #D5FF80 } /* Literal.String.Escape */ .highlight .sh { color: #D5FF80 } /* Literal.String.Heredoc */ .highlight .si { color: #D5FF80 } /* Literal.String.Interpol */ .highlight .sx { color: #D5FF80 } /* Literal.String.Other */ .highlight .sr { color: #95E6CB } /* Literal.String.Regex */ .highlight .s1 { color: #D5FF80 } /* Literal.String.Single */ .highlight .ss { color: #D5FF80 } /* Literal.String.Symbol */ .highlight .bp { color: #F28779 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #FFD173 } /* Name.Function.Magic */ .highlight .vi { color: #FFCC66 } /* Name.Variable.Instance */ .highlight .vm { color: #5CCFE6; font-style: italic } /* Name.Variable.Magic */ .highlight .il { color: #DFBFFF } /* Literal.Number.Integer.Long */

Usage

(Currently not fully documented, see the keymappings list for more.)

See tutor (accessible via hx --tutor or :tutor) for a vimtutor-like introduction.

Registers

Vim-like registers can be used to yank and store text to be pasted later. Usage is similar, with " being used to select a register:

If there is a selected register before invoking a change or delete command, the selection will be stored in the register and the action will be carried out:

Special Registers

Register character Contains
/ Last search
: Last executed command
" Last yanked text
_ Black hole

There is no special register for copying to system clipboard, instead special commands and keybindings are provided. See the keymap for the specifics. The black hole register works as a no-op register, meaning no data will be written to / read from it.

Surround

Functionality similar to vim-surround is built into helix. The keymappings have been inspired from vim-sandwich:

surround demo

ms acts on a selection, so select the text first and use ms<char>. mr and md work on the closest pairs found and selections are not required; use counts to act in outer pairs.

It can also act on multiple selections (yay!). For example, to change every occurrence of (use) to [use]:

Multiple characters are currently not supported, but planned.

Syntax-tree Motions

Alt-p, Alt-o, Alt-i, and Alt-n (or Alt and arrow keys) move the primary selection according to the selection's place in the syntax tree. Let's walk through an example to get familiar with them. Many languages have a syntax like so for function calls:

func(arg1, arg2, arg3)

A function call might be parsed by tree-sitter into a tree like the following.

(call
  function: (identifier) ; func
  arguments:
    (arguments           ; (arg1, arg2, arg3)
      (identifier)       ; arg1
      (identifier)       ; arg2
      (identifier)))     ; arg3

Use :tree-sitter-subtree to view the syntax tree of the primary selection. In a more intuitive tree format:

            ┌────┐
            │call│
      ┌─────┴────┴─────┐
      │                │
┌─────▼────┐      ┌────▼────┐
│identifier│      │arguments│
│  "func"  │ ┌────┴───┬─────┴───┐
└──────────┘ │        │         │
             │        │         │
   ┌─────────▼┐  ┌────▼─────┐  ┌▼─────────┐
   │identifier│  │identifier│  │identifier│
   │  "arg1"  │  │  "arg2"  │  │  "arg3"  │
   └──────────┘  └──────────┘  └──────────┘

Say we have a selection that wraps arg1. The selection is on the arg1 leaf in the tree above.

func([arg1], arg2, arg3)

Using Alt-n would select the next sibling in the syntax tree: arg2.

func(arg1, [arg2], arg3)

While Alt-o would expand the selection to the parent node. In the tree above we can see that we would select the arguments node.

func[(arg1, arg2, arg3)]

There is also some nuanced behavior that prevents you from getting stuck on a node with no sibling. If we have a selection on arg1, Alt-p would bring us to the previous child node. Since arg1 doesn't have a sibling to its left, though, we climb the syntax tree and then take the previous selection. So Alt-p will move the selection over to the "func" identifier.

[func](arg1, arg2, arg3)

Textobjects

textobject-demo textobject-treesitter-demo

Key after mi or ma Textobject selected
w Word
W WORD
p Paragraph
(, [, ', etc Specified surround pairs
m Closest surround pair
f Function
c Class
a Argument/parameter
o Comment
t Test
g Change

NOTE: f, c, etc need a tree-sitter grammar active for the current document and a special tree-sitter query file to work properly. Only some grammars currently have the query file implemented. Contributions are welcome!

Tree-sitter Textobject Based Navigation

Navigating between functions, classes, parameters, etc is made possible by leveraging tree-sitter and textobjects queries. For example to move to the next function use ]f, to move to previous class use [c, and so on.

tree-sitter-nav-demo

See the unimpaired section of the keybind documentation for the full reference.

NOTE: This feature is dependent on tree-sitter based textobjects and therefore requires the corresponding query file to work properly.