Compare commits
4 commits
6196c5fdd8
...
f201728457
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f201728457 | ||
|
|
e41ff1b7a5 | ||
|
|
d3e601e774 | ||
|
|
552417091d |
4 changed files with 152 additions and 23 deletions
47
help.md
47
help.md
|
|
@ -15,6 +15,7 @@ kitty_mod ctrl+alt
|
|||
For other editors you will probably have to disable or rebind them each
|
||||
individually.
|
||||
|
||||
|
||||
## Searching
|
||||
|
||||
Press ctrl+f to search this help file. Type a search term and press
|
||||
|
|
@ -22,15 +23,26 @@ ctrl+n/ctrl+p or f3/shift+f3 to jump through the matches. Press Enter
|
|||
to exit find mode at the current match or Escape to return to your
|
||||
starting point.
|
||||
|
||||
|
||||
## Messages and logs
|
||||
|
||||
Messages of issues regarding tasks that are not accomplished, like
|
||||
trying to close flow with unsaved files, as well as other information
|
||||
are shown briefly in the bottom status bar; most recent messages can
|
||||
be seen in the log view too, to open it, use ctrl+shift+p > `View log`;
|
||||
it's possible to make it taller dragging the toolbar with the mouse
|
||||
up or downwards.
|
||||
|
||||
|
||||
## Input Modes
|
||||
|
||||
Flow Control supports multiple input modes that may be changed
|
||||
interactively at runtime. The current input mode (and some other
|
||||
settings) is persisted in the configuration file automatically.
|
||||
|
||||
- f4 => Cycle major input modes (flow, vim, ...)
|
||||
- f4 => Cycle major input modes (flow, emacs, vim, helix,...)
|
||||
|
||||
The current input mode is displayed in the at the left side of the statusbar.
|
||||
The current input mode is displayed at the left side of the statusbar.
|
||||
|
||||
- ctrl+shift+p or alt+x => Show the command palette
|
||||
|
||||
|
|
@ -87,7 +99,7 @@ Multiple inheritance is supported with the `inherits` options like this:
|
|||
...
|
||||
```
|
||||
|
||||
## Flow mode
|
||||
### Flow mode
|
||||
|
||||
The default input mode, called just flow, is based on common GUI
|
||||
programming editors. It most closely resembles Visual Studio Code, but
|
||||
|
|
@ -98,19 +110,32 @@ cycle style of editing.
|
|||
See the `ctrl+f2` palette when flow mode is selected to see the full
|
||||
list of keybindings for this mode.
|
||||
|
||||
## Vim mode
|
||||
|
||||
### Vim mode
|
||||
|
||||
The vim modes, shown as NORMAL, INSERT or VISUAL in the status bar,
|
||||
follow the basic modal editing style of vim. The basics follow vim
|
||||
closely, but more advanced vim functions (e.g. macrosand registers)
|
||||
closely, but more advanced vim functions (e.g. macros and registers)
|
||||
are not supported (yet). Keybindings from flow mode that do not conflict
|
||||
with vim keybindings also work in vim mode.
|
||||
|
||||
|
||||
### Helix mode
|
||||
|
||||
The helix modes, shown as NOR, INS or SEL in the status bar, follow
|
||||
the basic modal editing style of helix. The basics are being adapted
|
||||
closely, more advanced functions (e.g. surround, macros, selections,
|
||||
registers) are not supported (yet). Usual keybinding with LSPs are
|
||||
used for tasks like 'go to definition', 'go to reference' and
|
||||
'inline documentation' featuring inline diagnostics. Keybindings
|
||||
from flow mode that do not conflict with helix keybindings also work in
|
||||
helix mode.
|
||||
|
||||
(work in progress)
|
||||
|
||||
### Mouse Commands
|
||||
## Mouse Commands
|
||||
|
||||
Mouse commands are not rebindable and are not listed in the command palette.
|
||||
Mouse commands are NOT rebindable and are not listed in the command palette.
|
||||
|
||||
- Left Click =>
|
||||
Clear all cursors and selections and the place cursor at the mouse pointer
|
||||
|
|
@ -170,7 +195,7 @@ animation_min_lag 0
|
|||
animation_max_lag 150
|
||||
```
|
||||
|
||||
Most of these options are fairly self explanitory.
|
||||
Most of these options are fairly self explanatory.
|
||||
|
||||
`theme`, `input_mode` and `show_whitespace` are automatically
|
||||
persisted when changed interactively with keybindings.
|
||||
|
|
@ -185,3 +210,9 @@ animation altogether.
|
|||
File types may be configured with the `Edit file type configuration` command. You
|
||||
can also create a new file type by adding a new `.conf` file to the `file_type`
|
||||
directory. Have a look at an existing file type to see what options are available.
|
||||
|
||||
## Flags and options
|
||||
|
||||
As every respectable terminal program, flow provide various invoking
|
||||
options that among others, will allow you to inspect various aspects of
|
||||
the running session. Feel free to run `flow --help` to explore them.
|
||||
|
|
|
|||
|
|
@ -134,6 +134,19 @@ pub fn is_dirty(self: *const Self) bool {
|
|||
return false;
|
||||
}
|
||||
|
||||
pub fn count_dirty_buffers(self: *const Self) usize {
|
||||
var count: usize = 0;
|
||||
var i = self.buffers.iterator();
|
||||
|
||||
while (i.next()) |p| {
|
||||
const buffer = p.value_ptr.*;
|
||||
if (!buffer.is_ephemeral() and buffer.is_dirty()) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
pub fn is_buffer_dirty(self: *const Self, file_path: []const u8) bool {
|
||||
return if (self.buffers.get(file_path)) |buffer| buffer.is_dirty() else false;
|
||||
}
|
||||
|
|
@ -149,6 +162,17 @@ pub fn save_all(self: *const Self) Buffer.StoreToFileError!void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn reload_all(self: *const Self) Buffer.LoadFromFileError!void {
|
||||
var i = self.buffers.iterator();
|
||||
while (i.next()) |kv| {
|
||||
const buffer = kv.value_ptr.*;
|
||||
if (buffer.is_ephemeral())
|
||||
buffer.mark_clean()
|
||||
else
|
||||
try buffer.refresh_from_file();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_all(self: *Self) void {
|
||||
var i = self.buffers.iterator();
|
||||
while (i.next()) |p| {
|
||||
|
|
@ -158,6 +182,49 @@ pub fn delete_all(self: *Self) void {
|
|||
self.buffers.clearRetainingCapacity();
|
||||
}
|
||||
|
||||
pub fn delete_others(self: *Self, protected: *Buffer) error{OutOfMemory}!void {
|
||||
var keys = try std.ArrayList(*[]const u8).initCapacity(self.allocator, self.buffers.size);
|
||||
defer keys.deinit(self.allocator);
|
||||
|
||||
var it = self.buffers.iterator();
|
||||
|
||||
while (it.next()) |p| {
|
||||
const buffer = p.value_ptr.*;
|
||||
if (buffer != protected) {
|
||||
try keys.append(self.allocator, p.key_ptr);
|
||||
}
|
||||
}
|
||||
for (keys.items) |k| {
|
||||
const buffer = self.buffers.get(k.*) orelse continue;
|
||||
_ = self.buffers.remove(k.*);
|
||||
buffer.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn close_others(self: *Self, protected: *Buffer) error{OutOfMemory}!usize {
|
||||
var remaining: usize = 0;
|
||||
var keys = try std.ArrayList(*[]const u8).initCapacity(self.allocator, self.buffers.size);
|
||||
defer keys.deinit(self.allocator);
|
||||
|
||||
var it = self.buffers.iterator();
|
||||
while (it.next()) |p| {
|
||||
const buffer = p.value_ptr.*;
|
||||
if (buffer != protected) {
|
||||
if (buffer.is_ephemeral() or !buffer.is_dirty()) {
|
||||
try keys.append(self.allocator, p.key_ptr);
|
||||
} else {
|
||||
remaining += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (keys.items) |k| {
|
||||
const buffer = self.buffers.get(k.*) orelse continue;
|
||||
_ = self.buffers.remove(k.*);
|
||||
buffer.deinit();
|
||||
}
|
||||
return remaining;
|
||||
}
|
||||
|
||||
pub fn buffer_from_ref(self: *Self, buffer_ref: usize) ?*Buffer {
|
||||
var i = self.buffers.iterator();
|
||||
while (i.next()) |p|
|
||||
|
|
|
|||
|
|
@ -273,7 +273,13 @@ const cmds = struct {
|
|||
const Result = command.Result;
|
||||
|
||||
pub fn quit(self: *Self, _: Ctx) Result {
|
||||
try self.check_all_not_dirty();
|
||||
const logger = log.logger("buffer");
|
||||
defer logger.deinit();
|
||||
self.check_all_not_dirty() catch |err| {
|
||||
const count_dirty_buffers = self.buffer_manager.count_dirty_buffers();
|
||||
logger.print("{} unsaved buffer(s), use 'quit without saving' to exit", .{count_dirty_buffers});
|
||||
return err;
|
||||
};
|
||||
try tp.self_pid().send("quit");
|
||||
}
|
||||
pub const quit_meta: Meta = .{ .description = "Quit" };
|
||||
|
|
|
|||
|
|
@ -60,20 +60,16 @@ const cmds_ = struct {
|
|||
}
|
||||
pub const wq_meta: Meta = .{ .description = "wq (write/save file and quit)" };
|
||||
|
||||
pub fn @"x!"(_: *void, _: Ctx) Result {
|
||||
try cmd("save_file", command.fmt(.{ "then", .{ "quit_without_saving", .{} } }));
|
||||
}
|
||||
pub const @"x!_meta": Meta = .{ .description = "x! (write/save file and exit, ignoring other unsaved changes)" };
|
||||
|
||||
pub fn x(_: *void, _: Ctx) Result {
|
||||
try cmd("save_file", command.fmt(.{ "then", .{ "quit", .{} } }));
|
||||
}
|
||||
pub const x_meta: Meta = .{ .description = "x (write/save file and quit)" };
|
||||
|
||||
// This one needs some help, the intention is to close only the current buffer
|
||||
// , if is the only buffer, exit...
|
||||
// TODO
|
||||
// pub fn @"x!"(_: *void, _: Ctx) Result {
|
||||
// try cmd("save_file", .{});
|
||||
// try cmd("close_file_without_saving", .{});
|
||||
// }
|
||||
// pub const @"x!_meta": Meta = .{ .description = "x! (write/save file and close forcefully, ignoring unsaved changes)" };
|
||||
|
||||
pub fn wa(_: *void, _: Ctx) Result {
|
||||
if (tui.get_buffer_manager()) |bm|
|
||||
bm.save_all() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
|
|
@ -94,7 +90,7 @@ const cmds_ = struct {
|
|||
try cmd("quit_without_saving", .{});
|
||||
}
|
||||
}
|
||||
pub const @"xa!_meta": Meta = .{ .description = "xa! (write all and quit forcefully, ignoring unsaved changes)" };
|
||||
pub const @"xa!_meta": Meta = .{ .description = "xa! (write all and exit, ignoring other unsaved changes)" };
|
||||
|
||||
pub fn wqa(_: *void, _: Ctx) Result {
|
||||
if (tui.get_buffer_manager()) |bm|
|
||||
|
|
@ -109,12 +105,18 @@ const cmds_ = struct {
|
|||
try cmd("quit_without_saving", .{});
|
||||
}
|
||||
}
|
||||
pub const @"wqa!_meta": Meta = .{ .description = "wqa! (write all and quit forcefully, ignoring unsaved changes)" };
|
||||
pub const @"wqa!_meta": Meta = .{ .description = "wqa! (write all and exit, ignoring unsaved changes)" };
|
||||
|
||||
pub fn rl(_: *void, _: Ctx) Result {
|
||||
try cmd("reload_file", .{});
|
||||
}
|
||||
pub const rl_meta: Meta = .{ .description = "rl (force reload current file)" };
|
||||
pub const rl_meta: Meta = .{ .description = "rl (reload current file)" };
|
||||
|
||||
pub fn rla(_: *void, _: Ctx) Result {
|
||||
if (tui.get_buffer_manager()) |bm|
|
||||
bm.reload_all() catch |e| return tp.exit_error(e, @errorReturnTrace());
|
||||
}
|
||||
pub const rla_meta: Meta = .{ .description = "rla (reload all files)" };
|
||||
|
||||
pub fn o(_: *void, _: Ctx) Result {
|
||||
try cmd("open_file", .{});
|
||||
|
|
@ -150,7 +152,30 @@ const cmds_ = struct {
|
|||
pub fn @"bc!"(_: *void, _: Ctx) Result {
|
||||
try cmd("close_file_without_saving", .{});
|
||||
}
|
||||
pub const @"bc!_meta": Meta = .{ .description = "bc! (Close buffer/tab forcefully, ignoring changes)" };
|
||||
pub const @"bc!_meta": Meta = .{ .description = "bc! (Close buffer/tab, ignoring changes)" };
|
||||
|
||||
pub fn @"bco!"(_: *void, _: Ctx) Result {
|
||||
const mv = tui.mainview() orelse return;
|
||||
if (tui.get_buffer_manager()) |bm| {
|
||||
if (mv.get_active_buffer()) |buffer| try bm.delete_others(buffer);
|
||||
}
|
||||
}
|
||||
pub const @"bco!_meta": Meta = .{ .description = "bco! (Close other buffers/tabs, discarding changes)" };
|
||||
|
||||
pub fn bco(_: *void, _: Ctx) Result {
|
||||
const logger = log.logger("helix-mode");
|
||||
defer logger.deinit();
|
||||
const mv = tui.mainview() orelse return;
|
||||
const bm = tui.get_buffer_manager() orelse return;
|
||||
if (mv.get_active_buffer()) |buffer| {
|
||||
const remaining = try bm.close_others(buffer);
|
||||
if (remaining > 0) {
|
||||
logger.print("{} unsaved buffer(s) remaining", .{remaining});
|
||||
try cmd("next_tab", .{});
|
||||
}
|
||||
}
|
||||
}
|
||||
pub const bco_meta: Meta = .{ .description = "bco (Close other buffers/tabs)" };
|
||||
|
||||
pub fn save_selection(_: *void, _: Ctx) Result {
|
||||
const logger = log.logger("helix-mode");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue