Skip to content

Commit 0bb11da

Browse files
committed
Added zoom mode & max width
1 parent 09b2f6a commit 0bb11da

File tree

11 files changed

+121
-10
lines changed

11 files changed

+121
-10
lines changed

book/src/editor.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ The `[editor.statusline]` key takes the following sub-keys:
106106

107107
| Key | Description | Default |
108108
| --- | --- | --- |
109-
| `left` | A list of elements aligned to the left of the statusline | `["mode", "spinner", "file-name", "read-only-indicator", "file-modification-indicator"]` |
109+
| `left` | A list of elements aligned to the left of the statusline | `["mode", "spinner", "file-name", "read-only-indicator", "zoom", "file-modification-indicator"]` |
110110
| `center` | A list of elements aligned to the middle of the statusline | `[]` |
111111
| `right` | A list of elements aligned to the right of the statusline | `["diagnostics", "selections", "register", "position", "file-encoding"]` |
112112
| `separator` | The character used to separate elements in the statusline | `"│"` |
@@ -139,6 +139,7 @@ The following statusline elements can be configured:
139139
| `spacer` | Inserts a space between elements (multiple/contiguous spacers may be specified) |
140140
| `version-control` | The current branch name or detached commit hash of the opened workspace |
141141
| `register` | The current selected register |
142+
| `zoom` | The current window zoom/zen state |
142143

143144
### `[editor.lsp]` Section
144145

book/src/generated/typable-cmd.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,4 @@
8888
| `:move`, `:mv` | Move the current buffer and its corresponding file to a different path |
8989
| `:yank-diagnostic` | Yank diagnostic(s) under primary cursor to register, or clipboard by default |
9090
| `:read`, `:r` | Load a file into buffer |
91+
| `:set-max-width` | Set the maximum width of the editor. If set to 0 it will take up the entire width. |

book/src/keymap.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ This layer is similar to Vim keybindings as Kakoune does not support windows.
274274
| `J` | Swap window downwards | `swap_view_down` |
275275
| `K` | Swap window upwards | `swap_view_up` |
276276
| `L` | Swap window to the right | `swap_view_right` |
277+
| `z` | Toggle zoom for the focused view | `toggle_zoom` |
277278

278279
#### Space mode
279280

book/src/remapping.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ k = "scroll_down"
6868
m = ":run-shell-command make"
6969
c = ":run-shell-command cargo build"
7070
t = ":run-shell-command cargo test"
71+
72+
# Creates a basic 'zen-mode' similar to VSCode's
73+
z = ["toggle_zoom", ":set-max-width 120 0", ":set gutters.layout []"]
7174
```
7275

7376
## Special keys and modifiers

helix-term/src/commands.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,7 @@ impl MappableCommand {
527527
vsplit_new, "Vertical right split scratch buffer",
528528
wclose, "Close window",
529529
wonly, "Close windows except current",
530+
toggle_zoom, "Toggle zoom for current window",
530531
select_register, "Select register",
531532
insert_register, "Insert register",
532533
align_view_middle, "Align view middle",
@@ -5475,6 +5476,11 @@ fn wonly(cx: &mut Context) {
54755476
}
54765477
}
54775478

5479+
fn toggle_zoom(cx: &mut Context) {
5480+
cx.editor.tree.zoom = !cx.editor.tree.zoom;
5481+
cx.editor.tree.recalculate();
5482+
}
5483+
54785484
fn select_register(cx: &mut Context) {
54795485
cx.editor.autoinfo = Some(Info::from_registers(&cx.editor.registers));
54805486
cx.on_next_key(move |cx, event| {

helix-term/src/commands/typed.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2539,6 +2539,44 @@ fn read(cx: &mut compositor::Context, args: &[Cow<str>], event: PromptEvent) ->
25392539
Ok(())
25402540
}
25412541

2542+
fn set_max_width(
2543+
cx: &mut compositor::Context,
2544+
args: &[Cow<str>],
2545+
event: PromptEvent,
2546+
) -> anyhow::Result<()> {
2547+
if event != PromptEvent::Validate {
2548+
return Ok(());
2549+
}
2550+
2551+
let mut args = args.iter();
2552+
let Some(width) = args.next() else {
2553+
bail!(":set-max-width takes 1 or 2 arguments")
2554+
};
2555+
let width: u16 = width.parse()?;
2556+
let alt_width: Option<u16> = args.next().map(|w| w.parse()).transpose()?;
2557+
2558+
let set_width = match alt_width {
2559+
Some(alt_width) if cx.editor.tree.max_width == width => {
2560+
cx.editor.tree.max_width = alt_width;
2561+
alt_width
2562+
}
2563+
_ => {
2564+
cx.editor.tree.max_width = width;
2565+
width
2566+
}
2567+
};
2568+
cx.editor.tree.recalculate();
2569+
2570+
if set_width == 0 {
2571+
cx.editor.set_status("Unset maximum width");
2572+
} else {
2573+
cx.editor
2574+
.set_status(format!("Set maximum width to {}", set_width));
2575+
}
2576+
2577+
Ok(())
2578+
}
2579+
25422580
pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
25432581
TypableCommand {
25442582
name: "quit",
@@ -3160,6 +3198,13 @@ pub const TYPABLE_COMMAND_LIST: &[TypableCommand] = &[
31603198
fun: read,
31613199
signature: CommandSignature::positional(&[completers::filename]),
31623200
},
3201+
TypableCommand {
3202+
name: "set-max-width",
3203+
aliases: &[],
3204+
doc: "Set the maximum width of the editor, or swap between 2 widths. If set to 0 it will take up the entire width.",
3205+
fun: set_max_width,
3206+
signature: CommandSignature::positional(&[completers::none]),
3207+
},
31633208
];
31643209

31653210
pub static TYPABLE_COMMAND_MAP: Lazy<HashMap<&'static str, &'static TypableCommand>> =

helix-term/src/keymap/default.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
208208
"C-s" | "s" => hsplit_new,
209209
"C-v" | "v" => vsplit_new,
210210
},
211+
"z" => toggle_zoom,
211212
},
212213

213214
// move under <space>c
@@ -273,6 +274,7 @@ pub fn default() -> HashMap<Mode, KeyTrie> {
273274
"C-s" | "s" => hsplit_new,
274275
"C-v" | "v" => vsplit_new,
275276
},
277+
"z" => toggle_zoom,
276278
},
277279
"y" => yank_to_clipboard,
278280
"Y" => yank_main_selection_to_clipboard,

helix-term/src/ui/editor.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ impl EditorView {
212212
);
213213
Self::render_rulers(editor, doc, view, inner, surface, theme);
214214

215-
// if we're not at the edge of the screen, draw a right border
216-
if viewport.right() != view.area.right() {
215+
// if we're not at the edge of the screen or zoomed, draw a right border
216+
if viewport.right() != view.area.right() && !editor.tree.zoom {
217217
let x = area.right();
218218
let border_style = theme.get("ui.window");
219219
for y in area.top()..area.bottom() {
@@ -1150,8 +1150,13 @@ impl EditorView {
11501150
..
11511151
} = *event;
11521152

1153+
// In zoom, only the focused view is interactable.
1154+
let zoom = cxt.editor.tree.zoom;
11531155
let pos_and_view = |editor: &Editor, row, column, ignore_virtual_text| {
1154-
editor.tree.views().find_map(|(view, _focus)| {
1156+
editor.tree.views().find_map(|(view, focus)| {
1157+
if zoom && !focus {
1158+
return None;
1159+
}
11551160
view.pos_at_screen_coords(
11561161
&editor.documents[&view.doc],
11571162
row,
@@ -1163,7 +1168,10 @@ impl EditorView {
11631168
};
11641169

11651170
let gutter_coords_and_view = |editor: &Editor, row, column| {
1166-
editor.tree.views().find_map(|(view, _focus)| {
1171+
editor.tree.views().find_map(|(view, focus)| {
1172+
if zoom && !focus {
1173+
return None;
1174+
}
11671175
view.gutter_coords_at_screen_coords(row, column)
11681176
.map(|coords| (coords, view.id))
11691177
})
@@ -1558,8 +1566,12 @@ impl Component for EditorView {
15581566
}
15591567

15601568
for (view, is_focused) in cx.editor.tree.views() {
1561-
let doc = cx.editor.document(view.doc).unwrap();
1562-
self.render_view(cx.editor, doc, view, area, surface, is_focused);
1569+
// If in zoom, only the focused document is rendered, with the unfocused ones being
1570+
// positioned off-screen.
1571+
if !cx.editor.tree.zoom || is_focused {
1572+
let doc = cx.editor.document(view.doc).unwrap();
1573+
self.render_view(cx.editor, doc, view, area, surface, is_focused);
1574+
}
15631575
}
15641576

15651577
if config.auto_info {

helix-term/src/ui/statusline.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ where
163163
helix_view::editor::StatusLineElement::Spacer => render_spacer,
164164
helix_view::editor::StatusLineElement::VersionControl => render_version_control,
165165
helix_view::editor::StatusLineElement::Register => render_register,
166+
helix_view::editor::StatusLineElement::Zoom => render_zoom,
166167
}
167168
}
168169

@@ -531,3 +532,12 @@ where
531532
write(context, format!(" reg={} ", reg), None)
532533
}
533534
}
535+
536+
fn render_zoom<F>(context: &mut RenderContext, write: F)
537+
where
538+
F: Fn(&mut RenderContext, String, Option<Style>) + Copy,
539+
{
540+
if context.editor.tree.zoom {
541+
write(context, "[zoom]".to_string(), None)
542+
}
543+
}

helix-view/src/editor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ impl Default for StatusLineConfig {
496496
E::Spinner,
497497
E::FileName,
498498
E::ReadOnlyIndicator,
499+
E::Zoom,
499500
E::FileModificationIndicator,
500501
],
501502
center: vec![],
@@ -595,6 +596,9 @@ pub enum StatusLineElement {
595596

596597
/// Indicator for selected register
597598
Register,
599+
600+
/// Current zoom/zen state
601+
Zoom,
598602
}
599603

600604
// Cursor shape is read and used on every rendered frame and so needs

0 commit comments

Comments
 (0)