Add initial docs for command, editor, keybind, palette

This commit is contained in:
Igor Támara 2025-10-19 01:05:57 -05:00 committed by CJ van den Berg
parent 1964cb7fd6
commit ca131d2135
4 changed files with 366 additions and 0 deletions

View file

@ -0,0 +1,121 @@
---
.title = "Commands",
.date = @date("2025-10-15T00:00:00"),
.author = "Igor Támara",
.layout = "tutorial.shtml",
.draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/architecture/command.md"},
---
Commands are actions triggered to operate on buffers primarily. They
are present in `editor`, `tui`, `mode` and `minimodes`, it's possible
to find commands in other places, which will become evident when the
need arises.
## Previous notes
Note: Flow is programmed with [zig](https://ziglang.org/), if you are familiar
with C, C++, Rust, there are differences and reasonings that
might find useful when [learning Zig](https://ziglang.org/learn/). If you
are coming from higher level programming languages such as Python, Ruby,
C#, Java, Golang, Typescript it will be an opportunity to learn about trades
of managing memory and fast responses and some lower level concepts present
in Zig. If you are brand new to programming, some general concepts will be
needed and practice in another language before getting into flow development.
If you are new to Zig, it's a good idea to take a look at
[ziglings](https://ziglings.org/) to practice, as you learn the language.
Maybe there is a [shell command invoked](/docs/architecture/keybind#shell) with a
keybinding that can help in the task you are aiming at before developing
flow itself.
## Understanding and creating commands
A command is a function with a type like
```zig
pub fn copy(self: *Self, _: Context) Result
```
and a `Meta` definition with the same name and suffix `_meta`.
```zig
pub const copy_meta: Meta = .{ .description = "Copy selection to clipboard" };
```
`copy` command is defined in `editor.zig`, which copies the current
selections into the pimp internal clipboard. Commands are available
to all the modes if defined as pub.
`meta` holds the description appearing in the command palette and optionally
has arguments, the most common, an integer, that usually constitutes a
repetition parameter, targeting vim, emacs and helix modes. As you dig in,
there might be particularities on the parameters accepted for a given
command.
## Invoking another command
Commands can be bound to mnemonics in modes by convention. For example, in
Vim Mode `vim.zig`, `q` corresponds to (quit), the most famous one.
```zig
pub fn q(_: *void, _: Ctx) Result {
try cmd("quit", .{});
}
pub const q_meta: Meta = .{ .description = "q (quit)" };
```
Looking more closely, the first parameter in this case is of `*void` type,
given that this command is defined in `vim.zig` which is calling the `quit`
command defined in `editor.zig`. `cmd` takes care of routing and finding
the command wherever it is defined.
## Chaining commands
Chaining commands is also common, and, by the way, swift. This is a sample
of applying first `save_file` command and then, the command `quit`.
```zig
pub fn wq(_: *void, _: Ctx) Result {
try cmd("save_file", command.fmt(.{ "then", .{ "quit", .{} } }));
}
pub const wq_meta: Meta = .{ .description = "wq (write file and quit)" };
```
Sometimes [keybinding](/docs/architecture/keybind) is enough to accomplish
a compound of already present commands, in others, zig programming is the
path to be taken.
# More in depth commands
Is common to define private functions in a given module that are invoked from
commands, as usual, functions are meant to be reused and help organize code.
For example, in hx mode `helix.zig` the `select_to_char_left_helix` command
uses the functions `helix_with_selections_const_arg` which iterates over all
cursels and applies the `select_cursel_to_char_left_helix` function.
```zig
pub fn select_to_char_left_helix(_: *void, ctx: Ctx) Result {
try helix_with_selections_const_arg(ctx, &select_cursel_to_char_left_helix);
}
```
## Sending parameters to commands
`cmd` is in charge of finding a command given its name, and parameters sent
to commands are vary for each command, for example, when interacting with
the clipboard, the messages sent are multiple chunks of information, for
now an example of such usage can be seen in a function that fetches contents
from the clipboard.
There are more advanced topics related to commands that are covered in the
[editor](/docs/architecture/editor), that deeps in specific details of
the editor and its interaction with cursors, selections and buffers
modifications, among others.
Learning about interactions with the buffer and editor is present in
[minimodes](/docs/architecture/minimode).

View file

@ -0,0 +1,76 @@
---
.title = "Editor",
.date = @date("2025-10-19T00:00:00"),
.author = "Igor Támara",
.layout = "tutorial.shtml",
.draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/architecture/editor.md"},
---
The `editor` coordinates visualization and modification of
buffer contents, multiple cursors, selections and marks.
To get the most of this section, it's recommended to have
read the [architecture briefing](/docs/architecture), about
[commands](/docs/architecture/command) and
[keybinds](/docs/architecture/keybind).
## Some concepts
The `primary Cursor` is presented always in the `Editor`,
signaling the part of the `Buffer` that can be modified and
manipulated as you see it. It scrolls on the current visible
portion of the buffer.
Other cursors can be in the `View` or in regions outside the
current view, depending on the size of both the buffer and
the editor view.
A `Selection` has two cursors that are not visible, they mark
the begin and the end of the selection, and CurSels are actually
what allow to have the concept of a cursor with a selection. A
`Cursel` has a cursor and optionally a Selection.
Most of editor operations act on the set of CurSels, the Primary
Cursor is in fact a CurSel, as opposed to what we previously
mentioned.
To complete the editor scenario, `Marks` have the potential
to become selections, and behind the scenes CurSels and are
evident to the eye when in search mode, they are seen as
the primary cursor is positioned over an occurrence with a
different color according to the theme.
The Editor will be acting on Buffer.Root which is the root of
the tree representing the document that is being edited. The API
of the Buffer.Root is stable and offers the necessary to insert,
delete and move along the buffer, knowing if the end, the
beginning has been reached when interacting with a Cursor.
## Editor Commands
We mentioned earlier that most of the operations work on all
the cursors and selections, there are various commands that
will use functions that iterate over cursors, selections, cursels
or marks. Given said this, we will be using functions as
parameters in most of the situations. Functional programming
languages are popular in these scenarios, to name a prominent
one, Emacs and emacs lisp.
If the buffer is not to be modified, we will be using `` to
get the root of it to find and position the cursors. While
we will use `` when the buffer is to be modified.
## Moving
## Selections
## Modifying the buffer
[Discord](https://discord.com/invite/4wvteUPphx) and
[Github issues](https://github.com/neurocyte/flow/issues) are the
main channels to do so.

View file

@ -0,0 +1,145 @@
---
.title = "Keybinding",
.date = @date("2025-10-19T00:00:00"),
.author = "Igor Támara",
.layout = "tutorial.shtml",
.draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/architecture/keybind.md"},
---
If you are here, it's possible that you already have edited your
own keybinds to suit your needs and are looking for some advanced
topics to extend your use cases and make everything easier and
fluid when in Flow. If you have not, take a peek to learning how
to do it.
Using the command palette `Ctrl+Shift+p` and typing **Edit key bindings**,
takes you to the json file to extend Flow configuring
keybindings to suit your needs.
[]($section.id('tldr'))
## ;TLDR;
Once you open the corresponding json file, locate inside the imode
(internal mode) that will accept the key or keys/combo and add an
array, where the first element is the combination to map to the
commands that will happen, the array accepts strings like in
```js
["ctrl+alt+shift+p", "open_command_palette"]
```
To avoid screwing up the combinations, and putting Flow in an unusable
state derived from a wrong mapping of key combinations, read on.
## Resetting keys to factory defaults
User configured keybindings are stored in Flow's configuration
directory under `keys/mode.json` where mode can be `flow`,
`emacs`, `vim`, `helix` or customized ones. Removing the keys
directory or the particular mode file can take you out from a
broken state.
## Keybinds for each mode
Keybinds are edited per mode, and other modes inherit what is
defined in your `flow.json` keybindings. Each mode override keybindings
of its parent mode. For example, if you are in **emacs** mode you will
be redirected to `emacs.json` and it will override the keybindings from
flow.
[introducing keybindings](/devlog/2024#2024-12-05T20:55:00) showcases
how to get to edit keybindings.
## Keybindings hierarchy
Some terminology
* **Mode**: Stored in a json file, like flow mode declared in `flow.json`.
* **Imode**: under the json file.
* **Major Imode**: `project` or descendant from `project`.
* **Minimodes**: To be used momentarily and do not inherit from `project`.
In general a keybinding json shows this hierarchy:
```
Mode > Imode > press > Key and commands
map > map > array > array(array(string,numbers),strings,numbers)
```
`Mode` is the json file that holds a map, where each
entry has a map called `press` that is an array of
arrays.
`project` is the main imode in `flow.json` and it can be
noticed that `normal` imode `inherit`s from `project`,
some modes have `release`, usually one will be using
only `press` inside `normal` imode or the specific mode
if inside `vim`, `helix` or `emacs` modes.
Looking further, it can be seen that
[minimodes](/docs/architecture/minimode) have their
keybinding mappings defined in a particular imode.
As stated previously, there is a mode hierarchy, the main mode
is flow and other modes inherit from it. We remind that also
imodes have a hierarchy and it's common for major imodes to be
descendants from `project`.
## Adding a Keybinding
The most basic case to map a keybind to a command was covered in
[TLDR](#tldr) which used the combination of three keys pressed
simultaneously `ctrl`, `shift` and `p`, all of them where combined
with `+` to execute the command `open_command_palette`.
A common use case is to add a keybinding to invoke an already
existing command and chain it to another, making Flow more suited to your
own needs.
[]($section.id('shell'))
## Running shell commands
For example, `f5` by default is used to run `zig build test`
outputting its results to a *scratch buffer* called `test`.
```js
["f5", ["create_scratch_buffer", "*test*"], ["shell_execute_insert", "zig", "build", "test"]],
```
Note that:
The keybind is `f5`, which maps to the `f5` keycode. is invoking
`create_scratchbuffer`, receiving the parameter `*test*` which
results in creating a scratch buffer if didn't exist. And
then executing the command `shell_execute_insert` that receives
the paramaters `zig`, `build`, `test`. This latter command is
executing a shell command called `zig` with the parameters
`build` and `test`; if you don't have zig installed, it will
not work, and you might want to remap f5 to a different shell
command.
```
[
"f5",
[
"create_scratch_buffer",
"*test*"
],
[
"shell_execute_insert",
"zig",
"build",
"test"
]
]
```
Observe [tasks running](/devlog/2025#2025-01-26T22:11:00) and maybe
consider using more keybindings or running tasks for your projects.
Probably binding commands is good, but maybe there is a feature in
other texts editors that you miss and would love to have it at
your fingertips. Then it's Zig time:
[Adding commands](/docs/architecture/command) to flow.

View file

@ -0,0 +1,24 @@
---
.title = "Palettes",
.date = @date("2025-10-20T00:00:00"),
.author = "Igor Támara",
.layout = "tutorial.shtml",
.draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/architecture/palette.md"},
---
Palettes are overlay menus that allow to select an item from the
presented list, applying a command with the selected element,
optionally deleting the selected item; it's possible to close
the palette without selecting(cancel), filter the elements, and
having special elements that trigger different actions.
To get the most of this section, it's recommended to have
read about [commands](/docs/architecture/command), and optionally
[minimodes](/docs/architecture/minimode).
See
[clipboard history palette](https://github.com/neurocyte/flow/commit/634a18cb5685a3c3fcfc08301306e628d33c3256)