Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 5 new commands to toggle text between PascalCase, camelCase, snake_case, Title Case and kebab-case #12043

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 20 additions & 2 deletions book/src/keymap.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
- [Goto mode](#goto-mode)
- [Match mode](#match-mode)
- [Window mode](#window-mode)
- [Case Mode](#case-mode)
- [Space mode](#space-mode)
- [Popup](#popup)
- [Completion Menu](#completion-menu)
Expand Down Expand Up @@ -70,8 +71,6 @@ Normal mode is the default mode when you launch helix. You can return to it from
| `r` | Replace with a character | `replace` |
| `R` | Replace with yanked text | `replace_with_yanked` |
| `~` | Switch case of the selected text | `switch_case` |
| `` ` `` | Set the selected text to lower case | `switch_to_lowercase` |
| `` Alt-` `` | Set the selected text to upper case | `switch_to_uppercase` |
| `i` | Insert before selection | `insert_mode` |
| `a` | Insert after selection (append) | `append_mode` |
| `I` | Insert at the start of the line | `insert_at_line_start` |
Expand Down Expand Up @@ -169,6 +168,7 @@ These sub-modes are accessible from normal mode and typically switch back to nor
| ----- | ----------- | ------- |
| `v` | Enter [select (extend) mode](#select--extend-mode) | `select_mode` |
| `g` | Enter [goto mode](#goto-mode) | N/A |
| ` ` ` | Enter [case mode](#case-mode) | N/A |
| `m` | Enter [match mode](#match-mode) | N/A |
| `:` | Enter command mode | `command_mode` |
| `z` | Enter [view mode](#view-mode) | N/A |
Expand Down Expand Up @@ -232,6 +232,24 @@ Jumps to various locations.
| `k` | Move up textual (instead of visual) line | `move_line_up` |
| `w` | Show labels at each word and select the word that belongs to the entered labels | `goto_word` |

#### Case mode

Accessed by typing ` ` ` in [normal mode](#normal-mode).

Various functions for changing case of text in different ways.

| Key | Description | Command |
| ----- | ----------- | ------- |
| `l` | Switch all text to lowercase | `switch_to_lowercase` |
| `u` | Switch all text to UPPERCASE | `switch_to_uppercase` |
| `p` | Switch text to Pascal Case | `switch_to_pascal_case` |
| `c` | Switch text to camelCase | `switch_to_camel_case` |
| `t` | Switch text to Title Case | `switch_to_title_case` |
| `s` | Switch text to snake_case | `switch_to_snake_case` |
| `k` | Switch text to kebab-case | `switch_to_kebab_case` |

TODO: Mappings for selecting syntax nodes (a superset of `[`).

#### Match mode

Accessed by typing `m` in [normal mode](#normal-mode).
Expand Down
1 change: 1 addition & 0 deletions helix-term/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ helix-loader = { path = "../helix-loader" }
anyhow = "1"
once_cell = "1.20"

heck = "0.5"
tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] }
tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] }
crossterm = { version = "0.28", features = ["event-stream"] }
Expand Down
40 changes: 37 additions & 3 deletions helix-term/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use helix_view::{
};

use anyhow::{anyhow, bail, ensure, Context as _};
use heck::{ToKebabCase, ToLowerCamelCase, ToSnakeCase, ToTitleCase, ToUpperCamelCase};
use insert::*;
use movement::Movement;

Expand Down Expand Up @@ -329,9 +330,14 @@ impl MappableCommand {
extend_prev_char, "Extend to previous occurrence of char",
repeat_last_motion, "Repeat last motion",
replace, "Replace with new char",
switch_case, "Switch (toggle) case",
switch_to_uppercase, "Switch to uppercase",
switch_to_alternate_case, "Switch to aLTERNATE cASE",
switch_to_uppercase, "Switch to UPPERCASE",
switch_to_lowercase, "Switch to lowercase",
switch_to_pascal_case, "Switch to PascalCase",
switch_to_camel_case, "Switch to camelCase",
switch_to_title_case, "Switch to Title Case",
switch_to_snake_case, "Switch to snake_case",
switch_to_kebab_case, "Switch to kebab-case",
page_up, "Move page up",
page_down, "Move page down",
half_page_up, "Move half page up",
Expand Down Expand Up @@ -1713,7 +1719,15 @@ where
exit_select_mode(cx);
}

fn switch_case(cx: &mut Context) {
fn switch_heck_case_impl(cx: &mut Context, change_fn: impl Fn(Tendril) -> String) {
switch_case_impl(cx, |string| {
let stri = Tendril::from_iter(string.chars());
let applied = change_fn(stri);
Tendril::from_iter(applied.chars())
});
}

fn switch_to_alternate_case(cx: &mut Context) {
switch_case_impl(cx, |string| {
string
.chars()
Expand All @@ -1730,6 +1744,26 @@ fn switch_case(cx: &mut Context) {
});
}

fn switch_to_pascal_case(cx: &mut Context) {
switch_heck_case_impl(cx, |str| str.to_upper_camel_case())
}

fn switch_to_camel_case(cx: &mut Context) {
switch_heck_case_impl(cx, |str| str.to_lower_camel_case())
}

fn switch_to_title_case(cx: &mut Context) {
switch_heck_case_impl(cx, |str| str.to_title_case())
}

fn switch_to_snake_case(cx: &mut Context) {
switch_heck_case_impl(cx, |str| str.to_snake_case())
}

fn switch_to_kebab_case(cx: &mut Context) {
switch_heck_case_impl(cx, |str| str.to_kebab_case())
}

fn switch_to_uppercase(cx: &mut Context) {
switch_case_impl(cx, |string| {
string.chunks().map(|chunk| chunk.to_uppercase()).collect()
Expand Down
13 changes: 10 additions & 3 deletions helix-term/src/keymap/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
"R" => replace_with_yanked,
"A-." => repeat_last_motion,

"~" => switch_case,
"`" => switch_to_lowercase,
"A-`" => switch_to_uppercase,
"~" => switch_to_alternate_case,
"`" => { "Case"
"l" => switch_to_lowercase,
"u" => switch_to_uppercase,
"p" => switch_to_pascal_case,
"c" => switch_to_camel_case,
"t" => switch_to_title_case,
"s" => switch_to_snake_case,
"k" => switch_to_kebab_case,
},

"home" => goto_line_start,
"end" => goto_line_end,
Expand Down