• Stars
    star
    411
  • Rank 101,935 (Top 3 %)
  • Language
    TypeScript
  • License
    ISC License
  • Created about 5 years ago
  • Updated 4 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Make your cursors dance with Kakoune-like modal editing in VS Code.

Dance

Kakoune-inspired key bindings, modes, menus and scripting for Visual Studio Code.

Huh?

Dance provides Kakoune-inspired commands and key bindings for Visual Studio Code, as well as support for custom modes and scripting.

Added key bindings are (mostly) compatible with Kakoune's, but are meant to be an addition to Visual Studio Code, rather than an emulation layer on top of it.

Why VS Code, and not Kakoune directly?

  • Kakoune is an efficient and lightweight editor with a very small ecosystem. VS Code is an entire IDE with a huge ecosystem and many existing extensions.
  • Kakoune is Unix-only.

Why Kakoune's key bindings, and not Vim's?

Why is it merely 'inspired' by Kakoune?

  • Unlike VSCodeVim which attempts to emulate Vim, Dance's only goal is to provide VS Code-native commands and key bindings that are inspired by Kakoune.
    • Some features are provided to mimic Kakoune's behavior (e.g. treating positions as coordinates of characters, rather than carets between characters like VS Code), but are optional.
  • Kakoune, Vim and VS Code are all fully-fledged text editors; therefore, they have overlapping features. For instance, where VSCodeVim provides its own multi-cursor and command engines to feel more familiar to existing Vim users, Dance leaves multi-cursor mode and editor commands to VS Code entirely.

User Guide

For most commands, the usage is the same as in Kakoune. However, the following changes have been made:

Custom modes

All modes are custom. By default, the normal and insert modes are defined, and many Kakoune-inspired keybindings are available. More modes can be created, though. These modes are configured with dance.modes.

For an example of this (which both creates a new mode and adds keybindings to it), see "Extend select mode" in the wiki.

Selection behaviors

Dance by default uses caret-based selections just like VS Code. This means a selection is anchored between two carets (i.e. positions between characters), and may be empty.

If you prefer character-based selections like Kakoune, please set "selectionBehavior": "character" in the configuration of the mode in which you wish to use character-based selections. This mode is designed to work with block-style cursors, so your configuration would typically look like:

"dance.modes": {
  "insert": {
    // ...
  },
  "normal": {
    "cursorStyle": "block",
    "selectionBehavior": "character",
    // ...
  }
},

If this is enabled, Dance will internally treat selections as inclusive ranges between two characters and imply that each selection contains at least one character.

Scripting

Most keybindings exposed by Dance are actually implemented by running several Dance commands in a row. For instance, dance.modes.set.normal is actually a wrapper around dance.modes.set with the argument { mode: "normal" }. Commands that take an input, like dance.modes.set, will prompt a user for a value if no argument is given.

Additionally to having commands with many settings, Dance also exposes the dance.run command, which runs JavaScript code. That code has access to the Dance API, and can perform operations with more control than Dance commands. Where Dance commands in the dance.selections namespace operate the same way on all selections at once, dance.run can be used to individually manipulate selections. It can also be used to run several commands at once.

Finally, the Dance API is exported by Dance. Other VS Code extensions can specify that they depend on Dance (with the extensionDependencies property), and then access the API by calling activate:

const { api } = await vscode.extensions.getExtension("gregoire.dance")
  .activate();

Pipes

Pipes no longer accept shell commands, but instead accept "expressions", those being:

  • #<shell command>: Pipes each selection into a shell command (the shell respects the terminal.integrated.automationProfile.<os> profile).

  • /<pattern>[/<replacement>[/<flags>]: A RegExp literal, as defined in JavaScript. Do note the addition of a replacement, for commands that add or replace text.

  • <JS expression>: A JavaScript expression in which the following variables are available:

    • $: Text of the current selection.
    • $$: Array of the text of all the selections.
    • i: Index of the current selection.
    • n: Number of selections in $$.

    Depending on the result of the expression, it will be inserted differently:

    • string: Inserted directly.
    • number: Inserted in its string representation.
    • boolean: Inserted as true or false.
    • null: Inserted as null.
    • undefined: Inserted as an empty string.
    • object: Inserted as JSON.
    • Any other type: Leads to an error.

Examples

  • /(\d+),(\d+)/$1.$2/g replaces 12,34 into 12.34.
  • i + 1 replaces 1,1,1,1,1 into 1,2,3,4,5, assuming that each selection is on a different digit.

Status bar

Dance provides several status bar segments (left-aligned) exposing info similar to Kakoune's default mode-line. Most of them are hidden by default and only shown contextually:

  • current mode: click to switch to another mode
  • macro recording status: click to stop recording
  • current count prefix: click to reset to 0
  • current register: click to unset
  • dance error: click to copy the full description of the last error

Dance view

Dance also provides a custom view which lists all registers and their contents.

Miscellaneous changes

A few changes were made from Kakoune, mostly out of personal preference, and to make the extension integrate better with VS Code.

  • The default yank register " maps to the system clipboard.
  • RegExps given to Dance commands support being given additional flags with the (?i) syntax (but only at the start of the pattern).
  • Registers can have arbitrary names. If the name of a register starts with a single space character, it will be local to the current document.
  • When using the default configuration (that is to say, these settings can be modified):
    • The cursor is not a block, but a line: Dance focuses on selections, and using a line instead of a block makes it obvious whether zero or one characters are selected. Besides, the line-shaped cursor is the default in VS Code.
    • Changing the mode will also change the editor.lineNumbers configuration value to on in insert mode, and relative in normal mode.

Troubleshooting

  • Dance uses the built-in VS Code key bindings, and therefore does not override the type command. However, it sometimes needs access to the type command, in dialogs and register selection, for instance. Consequently, it is not compatible with extensions that always override the type command, such as VSCodeVim; these extensions must therefore be disabled.
  • If you're on Linux and your keybindings don't work as expected (for instance, swapescape is not respected), take a look at the VS Code guide for troubleshooting Linux keybindings. TL;DR: adding "keyboard.dispatch": "keyCode" to your VS Code settings will likely fix it.

Contributing

Bugs

There are unfortunately still bugs lurking around. If you find one, please ensure that it has not been reported yet and submit a test that does not pass and can be used to reliably reproduce the bug.

Features

If you'd like to add or improve a feature, please make sure that no similar feature has been requested in the issues and file a new issue for it. This will ensure that no two people work on the same feature at the same time, and will be a good place to ask for help in case you want to tackle this yourself.
Since some features are not general enough, it may be requested of you to make a plugin that uses the Dance API or to simply use scripts in the meantime.

When contributing, please be mindful of the existing coding conventions and naming.

Your PR will be rebased on top of master in order to keep a clean commit history. Please avoid unnecessary commits (git commit --amend is your friend).

Misc.

Pre-release versions follow the pattern <major>.<minor>.<prev-patch><pre-release>, so for instance pre-release 1 of version 0.5.13 is 0.5.12001.

More Repositories

1

stadiacontroller

Command line application that emulates an Xbox 360 controller from a wired Stadia controller on Windows.
Go
171
star
2

scoop-better-shimexe

A better shim.exe file for Scoop.
C
70
star
3

logseq-snippets

Snippets I'm using with logseq.com.
JavaScript
62
star
4

BeatSinger

Beat Saber plugin for displaying floating lyrics while playing the game.
C#
43
star
5

Ryder

Runtime redirection of method calls for .NET Core.
C#
39
star
6

asmdot

[Unstable] Fast, zero-copy and lightweight (Arm | Mips | x86) assembler in (C | C++ | C# | Go | Haskell | Javascript | Nim | OCaml | Python | Rust).
Rust
37
star
7

Cometary

Roslyn extensions, with a touch of meta-programming.
C#
32
star
8

spotify-lyrics-windows

Real-time lyrics for Spotify on Windows, using Musixmatch and ReadProcessMemory (yikes).
F#
26
star
9

Rest.Fody

A multi-platform REST client powered by Fody, and heavily inspired by paulcbetts's Refit and canton7's RestEase.
C#
17
star
10

lesspass.rs

Rust library and CLI implementation of the LessPass password generator.
Rust
14
star
11

snowfall

Workflowy / Vimflowy inspired note-taking web-app. No longer maintained.
TypeScript
12
star
12

vscode-tree-sitter-api

Exposing Tree Sitter parsers and queries to VS Code extensions (with caching & more utilities).
TypeScript
12
star
13

ytm-lyrics

Lyrics for YouTube Music, using Musixmatch.
JavaScript
10
star
14

ricochet

Tiny (< 5kB) framework for efficient and direct DOM rendering, using JSX / observables.
TypeScript
6
star
15

async-if

Proof-of-concept generic async functions in Rust.
Rust
6
star
16

Focus-Window

PowerShell module / cmdlet used to focus any existing window, with built-in smart auto-completion.
PowerShell
5
star
17

Scry

Visual Studio extension that provides the ability to run C# scripts, giving them access to the current Roslyn workspace.
C#
4
star
18

wio-my-light

My bedside lamp, controlled by a button, gestures and the Internet.
C
4
star
19

cranelift-vscode

Cranelift IR support in VS Code.
TypeScript
4
star
20

Keystone.nim

Nim bindings for the Keystone assembler.
Nim
3
star
21

71.github.io

Personal website
HTML
3
star
22

wake

A minimalist Android Markdown editor.
Kotlin
3
star
23

chronos-to-gcalendar

Chronos to Google Calendar, for IONIS students.
Python
2
star
24

rss-to-keep

Add RSS items to Google Keep.
Python
2
star
25

nixcfg

Command line utility to query and modify .nix files.
Rust
2
star
26

spotify-lyrics-web

GreaseMonkey / ViolentMonkey script to display lyrics on the Spotify Web Player using Musixmatch.
JavaScript
2
star
27

dotfiles

My dotfiles, used with Nix on Debian and NixOS.
Nu
2
star
28

Fast.Fody

Quickly weave an assembly using C# or F# scripts, for extra productivity.
F#
2
star
29

oktjs

Open Korean Text transpiled to JavaScript.
Scala
2
star
30

virtualalloc

VirtualVec, a vector whose elements never move on resize; and VirtualAlloc, an allocator that can always resize in place.
Rust
2
star
31

LessPassForWindows

UWP client for lesspass in Fluent Design.
C#
2
star
32

computed-settings

Imports and other computations in your VS Code settings.
TypeScript
2
star
33

lesspass-pwa

An offline PWA for LessPass built to be light and beautiful.
TypeScript
2
star
34

AnyConstraint.Analyzer

Analyzer that suppresses the CS0702 error, thus allowing any constraint to be used (including 'Delegate' and 'Enum').
C#
2
star
35

IndexesStartAtOne

One-indexing in C#, right now. You know you want it.
C#
1
star
36

subspace

Light desktop application for downloading subtitles from OpenSubtitles, by simply dragging and dropping video files on a GUI.
C#
1
star
37

PlaySheet

Modern and extensible media player built on MPV, and with F# / WPF.
F#
1
star
38

netflix-no-cc

Dead simple web extension used to remove closed captions on Netflix.
JavaScript
1
star
39

getch

getch for Nim
Nim
1
star
40

PolyphasicSleep

An Android app that helps the user track a fully-custom polyphasic sleep cycle.
Kotlin
1
star
41

babel-plugin-transform-raw-jsx

JSX -> HTMLElement direct DOM rendering, via Babel.
TypeScript
1
star
42

MetalSharp

[Unmaintained] A type-safe F# assembler currently targeting x86 and ARM.
F#
1
star
43

ExpandableAllocator

A low-level .NET allocator that grows lazily.
C#
1
star
44

notes

Miscellaneous articles imported from Medium.
1
star
45

chronos-ql

GraphQL wrapper around the Chronos (http://chronos.epita.net; no longer available) API.
TypeScript
1
star
46

styx-history

Previous iterations of the Styx project.
Rust
1
star
47

blur

[No longer maintained] Run and edit a C# assembly at the same time. Convert LINQ Expressions and delegates to Mono.Cecil method bodies as well.
C#
1
star
48

runas.rs

Shortcuts for running executables as another user in Windows
Rust
1
star
49

replay.nu

Run bash commands and keep their environment in Nushell.
Nu
1
star
50

llvm.nim

LLVM bindings for Nim (versions 3.7, 3.8, 3.9, 4.0, and 5.0).
Nim
1
star
51

cell-family

#[no_std] cell "families" inspired by qcell's T[L]Cell
Rust
1
star
52

lesspass.kt

Android app for LessPass. Open-source, minimal, feature-full. Support for autofill manager planned.
Kotlin
1
star
53

study-korean

Materials for me to study Korean.
JavaScript
1
star