Links between developer docs

This commit is contained in:
Igor Támara 2025-10-29 16:43:37 -05:00 committed by CJ van den Berg
parent 5eedc17542
commit e837a66b97
10 changed files with 318 additions and 243 deletions

View file

@ -45,7 +45,7 @@ Some [custom frontmatter](https://zine-ssg.io/docs/supermd/#frontmatter) fields
Directs to contribute editing this documentation. Used by `layout/tutorial.shtml`. Directs to contribute editing this documentation. Used by `layout/tutorial.shtml`.
```ziggy ```ziggy
.githubedit** = "/docs/testing.md", .githubedit** = "/docs/testing.smd",
``` ```
### codepath (Optional) ### codepath (Optional)

View file

@ -44,27 +44,32 @@ offers services around the set of projects.
[]($section.id("commands")) []($section.id("commands"))
## Editor commands and modes ## Editor commands and modes
When a buffer is active, it has an `Editor` attached to it; an editor When a buffer is active, it has an [Editor](/docs/architecture/editor)
might have associated tree-sitter support, given the file type detected, attached to it; an editor might have associated tree-sitter support,
and offers common services that are aimed to be used by `Commands` to given the file type detected, and offers common services that are aimed
manipulate the contents of a buffer at a higher level, the selections, to be used by `Commands` to manipulate the contents of a buffer at a
cursors, cursor selections `CurSel` and the `View`. The commands are higher level, the selections, cursors, cursor selections `CurSel` and
used by `Modes` with `Keybindings`. The main mode is Flow and the the `View`. [Commands](/docs/architecture/command) are used by `Modes`
keybindings can be used to map to a mode built up entirely on solely with [Keybindings](/docs/architecture/keybind). The main mode is Flow
calling already created commands. An example of a mode created by and the keybindings can be used to map to a mode built up entirely on
command composition is `Emacs` mode, for instance, it's possible to solely calling already created commands. An example of a mode
create a nano mode with just keybindings. In the other hand, `Vim` and created by command composition is `Emacs` mode, for instance, it's
`Helix` modes have particular definitions for commands that interact possible to create a nano mode with just keybindings. In the other hand,
with the buffers, being modal editors. `Vim` and [Helix](/docs/mode/helix) modes have particular definitions
for commands that interact with the buffers, being modal editors.
[]($section.id("tui")) []($section.id("tui"))
## Text user interface ## Text user interface
`Tui` governs it all offering support for `Palettes` that are known `Tui` governs it all offering support for
in other environments as pickers, as well as offering information [palettes](/docs/architecture/palette) that are known in other
through a set of `_views` (i.e. `logview`, `inputview`, environments as pickers, as well as offering information through a
`inspector_view`) and `status` (i.e. `tabs`, `clock`, `branch`, set of `_views` (i.e. `logview`, `inputview`, `inspector_view`) and
`linenum`). `status` (i.e. `tabs`, `clock`, `branch`, `linenum`), in the statusbar
[minimodes](/docs/architecture/minimode) will be present too, those
that receive more keypresses to offer additional functionality, such
as finding in files, finding in the current buffer, open files
and replacing a character.
[]($section.id("oses")) []($section.id("oses"))
## Operating systems and UI ## Operating systems and UI
@ -77,16 +82,16 @@ and Android via Termux, while in Windows there is an special GUI.
## Communication between components ## Communication between components
[Thespian](https://github.com/neurocyte/thespian) is in charge of [Thespian](https://github.com/neurocyte/thespian) is in charge of
processes synchronization and allows sending messages between processes synchronization and allows sending
different flow components, for example, when a widget needs [messages between different flow components](/docs/architecture/inner_data_exchange),
updating information from changing states of internal data and for example, when a widget needs updating information from changing
when components or external processes take time and need to return states of internal data and when components or external processes take
an answer, all this without blocking the user interface. Tree-sitter time and need to return an answer, all this without blocking the user
queries to highlight the current file of a particular interface. Tree-sitter queries to highlight the current file of a
language and LSPs usually take time by the nature of operations they particular language and LSPs usually take time by the nature of
perform, integration with git and running a `shell` command via a operations they perform, integration with git and running a `shell`
`task` all are coordinated thanks to the infrastructure that command via a `task` all are coordinated thanks to the infrastructure
Thespian provides. that Thespian provides.
[]($section.id("languages")) []($section.id("languages"))
## Programming languages support ## Programming languages support
@ -111,7 +116,7 @@ feedback via `logview`. To view logs use `f11` to toggle the
previous messages, or alternatively, open flow with the option previous messages, or alternatively, open flow with the option
`--show-logs`. `--show-logs`.
To log something import To log something, first import
```zig ```zig
const log = @import("log"); const log = @import("log");
@ -135,13 +140,14 @@ logger.print("{} unsaved buffer(s) remaining", .{remaining});
### View key presses ### View key presses
There are situations when you press some keys without the expected There are situations when you press some keys without the expected
behavior happening, to review if flow is getting the keys, or your desktop behavior happening, to review if flow is getting the keys, or your
environment or something else are capturing them, you will want to desktop environment or something else are capturing them, you will want
invoke flow with the option `--show-input`. to invoke flow with the option `--show-input`.
[]($section.id("next")) []($section.id("next"))
## Next steps ## Next steps
* [Guidelines for contributions](/docs/contributing) * [Guidelines for contributions](/docs/contributing)
* [Take a peek on testing](/docs/testing) * [Take a peek on testing](/docs/testing)
* [Configure some keybinds](/docs/architecture/keybind)
* [Back to docs](/docs) * [Back to docs](/docs)

View file

@ -4,32 +4,36 @@
.author = "Igor Támara", .author = "Igor Támara",
.layout = "tutorial.shtml", .layout = "tutorial.shtml",
.draft = false, .draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/architecture/command.md"}, .custom = {
.githubedit = "/docs/architecture/command.smd",
.codepath = "src/tui/editor.zig",
},
--- ---
Commands are actions triggered to operate on buffers primarily. They Commands are actions triggered to operate on buffers primarily. They are
are present in `editor`, `tui`, `mode` and `minimodes`, it's possible present in `editor`, `tui`, `mode` and `minimodes`, it's possible to find
to find commands in other places, which will become evident when the commands in other places, which will become evident when the need arises.
need arises.
[]($section.id('notes'))
## Previous notes ## Previous notes
Note: Flow is programmed with [zig](https://ziglang.org/), if you are familiar Note: Flow is programmed with [zig](https://ziglang.org/), if you are
with C, C++, Rust, there are differences and reasonings that familiar with C, C++, Rust, there are differences and reasonings that might
might find useful when [learning Zig](https://ziglang.org/learn/). If you find useful when [learning Zig](https://ziglang.org/learn/). If you are
are coming from higher level programming languages such as Python, Ruby, coming from higher level programming languages such as Python, Ruby, C#,
C#, Java, Golang, Typescript it will be an opportunity to learn about trades Java, Golang, Typescript it will be an opportunity to learn about trades of
of managing memory and fast responses and some lower level concepts present managing memory and fast responses and some lower level concepts present in
in Zig. If you are brand new to programming, some general concepts will be Zig. If you are brand new to programming, some general concepts will be
needed and practice in another language before getting into flow development. 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 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. [ziglings](https://ziglings.org/) to practice, as you learn the language.
Maybe there is a [shell command invoked](/docs/architecture/keybind#shell) with a Maybe there is a [shell command invoked](/docs/architecture/keybind#shell)
keybinding that can help in the task you are aiming at before developing with a keybinding that can help in the task you are aiming at before
flow itself. developing flow itself.
[]($section.id('creating'))
## Understanding and creating commands ## Understanding and creating commands
A command is a function with a type like A command is a function with a type like
@ -45,8 +49,8 @@ pub const copy_meta: Meta = .{ .description = "Copy selection to clipboard" };
``` ```
`copy` command is defined in `editor.zig`, which copies the current `copy` command is defined in `editor.zig`, which copies the current
selections into the pimp internal clipboard. Commands are available selections into the pimp internal clipboard. Commands are available to all
to all the modes if defined as pub. the modes if defined as pub.
`meta` holds the description appearing in the command palette and optionally `meta` holds the description appearing in the command palette and optionally
has arguments, the most common, an integer, that usually constitutes a has arguments, the most common, an integer, that usually constitutes a
@ -54,6 +58,7 @@ repetition parameter, targeting vim, emacs and helix modes. As you dig in,
there might be particularities on the parameters accepted for a given there might be particularities on the parameters accepted for a given
command. command.
[]($section.id('calling'))
## Invoking another command ## Invoking another command
Commands can be bound to mnemonics in modes by convention. For example, in Commands can be bound to mnemonics in modes by convention. For example, in
@ -71,6 +76,7 @@ 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 command defined in `editor.zig`. `cmd` takes care of routing and finding
the command wherever it is defined. the command wherever it is defined.
[]($section.id('tldr'))
## Chaining commands ## Chaining commands
Chaining commands is also common, and, by the way, swift. This is a sample Chaining commands is also common, and, by the way, swift. This is a sample
@ -87,10 +93,12 @@ Sometimes [keybinding](/docs/architecture/keybind) is enough to accomplish
a compound of already present commands, in others, zig programming is the a compound of already present commands, in others, zig programming is the
path to be taken. path to be taken.
# More in depth commands []($section.id('deepen'))
## More in depth commands
Is common to define private functions in a given module that are invoked from Is common to define private functions in a given module that are invoked
commands, as usual, functions are meant to be reused and help organize code. 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 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 uses the functions `helix_with_selections_const_arg` which iterates over all
@ -102,20 +110,40 @@ pub fn select_to_char_left_helix(_: *void, ctx: Ctx) Result {
} }
``` ```
## Sending parameters to commands []($section.id('command_arguments'))
### Sending parameters to commands
`cmd` is in charge of finding a command given its name, and parameters sent `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 to commands vary for each command.
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.
The command `goto_line`, which receives as parameter an integer(in the case
of vim and helix mode, you first type the number and then the action, gg)
as stated in its meta:
```zig
pub const goto_line_meta: Meta = .{ .arguments = &.{.integer} };
```
There are more advanced topics related to commands that are covered in the and to actually receiving the integer parameter:
[editor](/docs/architecture/editor), that deeps in specific details of
the editor and its interaction with cursors, selections and buffers ```zig
pub fn goto_line(self: *Self, ctx: Context) Result {
var line: usize = 0;
if (!try ctx.args.match(.{tp.extract(&line)}))
return error.InvalidGotoLineArgument;
```
[]($section.id('next'))
## Next steps
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. modifications, among others.
Learning about interactions with the buffer and editor is present in Learning about interactions with the buffer and editor is present in
[minimodes](/docs/architecture/minimode). [minimodes](/docs/architecture/minimode).
* [Add tests](/docs/testing) to harden your code
* [Back to architecture](/docs/architecture)

View file

@ -5,13 +5,7 @@
.layout = "tutorial.shtml", .layout = "tutorial.shtml",
.draft = false, .draft = false,
.custom = { .custom = {
.githubedit = "docs/architecture/editor.md", .githubedit = "docs/architecture/editor.smd",
.prevurl = "docs/command",
.prevtext = "Commands",
.topurl = "docs/architecture",
.toptext = "Architecture",
.nexturl = "docs/architecture/minimode",
.nexttext = "Mini modes",
.codepath ="src/tui/editor.zig", .codepath ="src/tui/editor.zig",
}, },
--- ---
@ -24,6 +18,7 @@ read the [architecture briefing](/docs/architecture), about
[commands](/docs/architecture/command) and [commands](/docs/architecture/command) and
[keybinds](/docs/architecture/keybind). [keybinds](/docs/architecture/keybind).
[]($section.id("concepts"))
## Some concepts ## Some concepts
The `primary Cursor` is presented always in the `Editor`, The `primary Cursor` is presented always in the `Editor`,
@ -63,6 +58,7 @@ also sometimes receive metrics from the editor that help determine
if a cursor is about to exit boundaries of the buffer and have if a cursor is about to exit boundaries of the buffer and have
everything "in place". everything "in place".
[]($section.id("commands"))
## Editor Commands ## Editor Commands
We mentioned earlier that most of the operations work on all We mentioned earlier that most of the operations work on all
@ -85,6 +81,7 @@ thinking only in the current cursor and if required, the
operation will be applied to all the cursors, the same applies operation will be applied to all the cursors, the same applies
to selections, cursels and marks. to selections, cursels and marks.
[]($section.id("moving"))
## Moving ## Moving
For example, to move the cursors a page up, we can look at For example, to move the cursors a page up, we can look at
@ -103,6 +100,7 @@ The family of `move` functions is big, look for the methods
whose name has the word move in them. with the command palette whose name has the word move in them. with the command palette
is possible to get a glimpse of them. is possible to get a glimpse of them.
[]($section.id("selecting"))
## Selections ## Selections
There are naming conventions for the functions that help There are naming conventions for the functions that help
@ -138,6 +136,7 @@ fn with_selection_and_view_const
fn with_selections_and_view_const fn with_selections_and_view_const
``` ```
[]($section.id("modifying"))
## Modifying the buffer ## Modifying the buffer
The `select` family of functions is bigger than the set of `move` The `select` family of functions is bigger than the set of `move`
@ -151,3 +150,10 @@ place and then applying the modification.
[Github issues](https://github.com/neurocyte/flow/issues) are the [Github issues](https://github.com/neurocyte/flow/issues) are the
main channels to do so. main channels to do so.
[]($section.id("next"))
## Next steps
* [minimodes](/docs/architecture/minimode) invoke commands defined in the editor
* [palettes](/docs/architecture/palette) are open by commands and when selected an item, a command
is invoked.
* Plenty of [commands](/docs/architecture/command) are defined in the editor.

View file

@ -6,42 +6,40 @@
.draft = false, .draft = false,
.custom = { .custom = {
.githubedit = "docs/architecture/inner_data_exchange.smd", .githubedit = "docs/architecture/inner_data_exchange.smd",
.prevurl = "docs/architecture/editor.zig",
.prevtext = "Editor",
.topurl = "docs/architecture",
.toptext = "Architecture",
.codepath ="src/tui/editor.zig", .codepath ="src/tui/editor.zig",
}, },
--- ---
Flow uses actor model to offer an snappy experience when working with Flow uses actor model to offer an snappy experience when working with
projects that have tens of thousands of source files, also features async projects that have tens of thousands of source files, also features
communication with the threads that are working in independent tasks that async communication with the threads that are working in independent
contribute to have vcs, lsp and tree-sitter integration, apart from the tasks that contribute to have vcs, lsp and tree-sitter integration,
directory introspection to make available what is expected from an IDE. The apart from the directory introspection to make available what is
command arguments travel to the target command and are en/decoded powered by expected from an IDE. The command arguments travel to the target
[cbor](https://github.com/neurocyte/cbor), the same as the parameters that command and are en/decoded powered by
are sent from one thread to another. The process management is provided by [cbor](https://github.com/neurocyte/cbor), the same as the parameters
[thespian](https://github.com/neurocyte/thespian). that are sent from one thread to another. The process management is
provided by [thespian](https://github.com/neurocyte/thespian).
This chapter describes the mechanisms that flow has to pass arguments This chapter describes the mechanisms that flow has to pass arguments
between components. between components.
[]($section.id('libraries'))
## Library usage ## Library usage
* The Thespian library sends and receives `thespian.message` values, which * The Thespian library sends and receives `thespian.message` values,
are strongly typed, but schema free CBOR encoded structures. It supports which are strongly typed, but schema free CBOR encoded structures.
spawning, linking, killing, etc., of lightweight processes (aka the "Actor It supports spawning, linking, killing, etc., of lightweight processes
Model" with "Green Threads") and provides async file and network IO and (aka the "Actor Model" with "Green Threads") and provides async file
child process management. and network IO and child process management.
* The CBOR library encodes decodes CBOR structured data to/from Zig * The CBOR library encodes decodes CBOR structured data to/from Zig
variables variables
* Encoding happens via the `cbor.write*` functions. These are wrapped by * Encoding happens via the `cbor.write*` functions. These are wrapped
`command.fmt` and `thespian.message.fmt` which provide fast allocation by `command.fmt` and `thespian.message.fmt` which provide fast
free encoding to a thread local buffer. Note that the CBOR data encoded allocation free encoding to a thread local buffer. Note that the CBOR
via the `*.fmt` functions will only survive until another message is data encoded via the `*.fmt` functions will only survive until another
encoded and must be copied somewhere for more permanent storage, or message is encoded and must be copied somewhere for more permanent
possibly sent somewhere via thespian. storage, or possibly sent somewhere via thespian.
* Decoding happens via the `cbor.match`, `cbor.extract` and * Decoding happens via the `cbor.match`, `cbor.extract` and
`cbor.extractAlloc` group of functions. `cbor.extract` functions do not `cbor.extractAlloc` group of functions. `cbor.extract` functions do not
allocate and cannot be used to extract some types that require allocation. allocate and cannot be used to extract some types that require allocation.
@ -51,31 +49,19 @@ variables
data buffer. `thespian.message.match` and `thespian.extract` functions data buffer. `thespian.message.match` and `thespian.extract` functions
are fairly simple wrappers. are fairly simple wrappers.
### Example of command argument usage The most basic example on deserialization of an integer value can is shown
in [commands](/docs/architecture/command#command_arguments).
The command `goto_line`, which receives as parameter an integer(in the case Cbor features en/decoding arrays, json and compounds of basic types and the
of vim and helix mode, you first type the number and then the action, gg) only requirement is to decode in the same order as encoding the data, more
via its meta is declared as: samples on using cbor can be seen in
```zig
pub const goto_line_meta: Meta = .{ .arguments = &.{.integer} };
```
To actually receiving the integer parameter:
```zig
pub fn goto_line(self: *Self, ctx: Context) Result {
var line: usize = 0;
if (!try ctx.args.match(.{tp.extract(&line)}))
return error.InvalidGotoLineArgument;
```
Cbor features en/decoding arrays and compounds of basic types and the only
requirement is to decode in the same order as encoding the data, more
samples of usage can be seen in
[cbor tests](https://github.com/neurocyte/cbor/blob/master/test/tests.zig). [cbor tests](https://github.com/neurocyte/cbor/blob/master/test/tests.zig).
For example, when interacting with the clipboard, the messages sent are
multiple chunks of information,
[]($section.id('scoping'))
## Buffer scoping ## Buffer scoping
CBOR structures are mostly stored in a way that avoids allocation entirely. CBOR structures are mostly stored in a way that avoids allocation entirely.
@ -118,6 +104,17 @@ from.
CBOR data and will be invalidated implicitly when the CBOR buffer they came CBOR data and will be invalidated implicitly when the CBOR buffer they came
from is invalidated/overwritten. from is invalidated/overwritten.
[]($section.id('next'))
## Next steps
Serialization and deserialization occurs almost everywhere
* [Editor](/docs/architecture/editor)
* [Commands](/docs/architecture/command)
* [Minimodes](/docs/architecture/minimode)
* [Architecture](/docs/architecture)
[]($section.id('more'))
## More information ## More information
* [Deepwiki on cbor](https://deepwiki.com/neurocyte/cbor) * [Deepwiki on cbor](https://deepwiki.com/neurocyte/cbor)

View file

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

View file

@ -4,7 +4,10 @@
.author = "Igor Támara", .author = "Igor Támara",
.layout = "tutorial.shtml", .layout = "tutorial.shtml",
.draft = false, .draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/architecture/minimode.md"}, .custom = {
.githubedit = "/docs/architecture/minimode.smd",
.codepath ="src/tui/mode/mini/",
},
--- ---
Minimodes can be used by other modes adding functionality Minimodes can be used by other modes adding functionality
@ -15,6 +18,7 @@ open/save a file, and, in modal modes(like vim and helix).
An example of the latter is using numeric prefixes to An example of the latter is using numeric prefixes to
repeat an action many times. repeat an action many times.
[]($section.id("anatomy"))
## Anatomy of minimodes ## Anatomy of minimodes
To create a minimode it's needed: To create a minimode it's needed:
@ -23,6 +27,7 @@ To create a minimode it's needed:
* An Action mapping * An Action mapping
* A Minimode definition * A Minimode definition
[]($section.id("keybind"))
### Keybinding ### Keybinding
When a key or a keystroke(set of keys) are pressed, the When a key or a keystroke(set of keys) are pressed, the
@ -34,6 +39,7 @@ and look for `mini_find`, where you will know which
specific actions are triggered by the keybindings of the specific actions are triggered by the keybindings of the
minimode. minimode.
[]($section.id("mapping"))
### Action mapping ### Action mapping
Actions executed by each minimode are stored one per Actions executed by each minimode are stored one per
@ -46,6 +52,7 @@ Look for `mini` inside `tui.zig` to find out which minimodes
are present and where to look to learn how each minimode are present and where to look to learn how each minimode
does its own task. does its own task.
[]($section.id("definition"))
### Minimode definition ### Minimode definition
Possibly the simplest minimode that does not require Possibly the simplest minimode that does not require
@ -99,6 +106,7 @@ All the keys were handled and managed by the default "invisible"
widget that processes the keys for the minimode. And there is widget that processes the keys for the minimode. And there is
room for custom widgets that are explained next. room for custom widgets that are explained next.
[]($section.id("custom_widgets"))
## A custom widget ## A custom widget
When there is a need for an specialized widget, it's possible to When there is a need for an specialized widget, it's possible to
@ -106,7 +114,10 @@ define one, for example, the `file_browser` is used to load and
save files, and `numeric_input` is used to set the tab width for save files, and `numeric_input` is used to set the tab width for
example(look for it in the command palette `:`). example(look for it in the command palette `:`).
[]($section.id("next"))
## Next steps
* Head to [architecture](/docs/architecture) * Head to [architecture](/docs/architecture)
* Learn about [commands](/docs/architecture/command) * Review [commands](/docs/architecture/command)
* Deep in the [editor](/docs/architecture/editor)
* Review [keybindings](/docs/architecture/keybind) * Review [keybindings](/docs/architecture/keybind)

View file

@ -5,35 +5,30 @@
.layout = "tutorial.shtml", .layout = "tutorial.shtml",
.draft = false, .draft = false,
.custom = { .custom = {
.githubedit = "docs/architecture/palette.md", .githubedit = "docs/architecture/palette.smd",
.prevurl = "docs/minimode",
.prevtext = "Mini modes",
.topurl = "docs/architecture",
.toptext = "Architecture",
.codepath ="src/tui/mode/overlay/clipboard_palette.zig", .codepath ="src/tui/mode/overlay/clipboard_palette.zig",
}, },
--- ---
Palettes are overlay menus that allow to select an item from the Palettes are overlay menus that allow to select an item from the
presented list, applying a command with the selected element, presented list, applying a command with the selected element, optionally
optionally deleting the selected item; it's possible to close deleting the selected item; it's possible to close the palette without
the palette without selecting anything(a.k.a. cancel), filter selecting anything(a.k.a. cancel), filter the elements, and having
the elements, and having special elements that trigger different special elements that trigger different actions.
actions.
Examples of palettes are command_palette, clipboard_palette, Examples of palettes are command_palette, clipboard_palette, they all
they all are based on palette.zig that does all the heavy lifting are based on palette.zig that does all the heavy lifting and sets the
and sets the framework to create new palettes as simple as framework to create new palettes as simple as possible.
possible.
Palettes are an special case of minimode and for instance a Palettes are an special case of minimode and for instance a mode, they
mode, they receive inputs from keyboards and execute the receive inputs from keyboards and execute the beforehand mentioned
beforehand mentioned actions in response. actions in response.
To get the most of this section, it's recommended to have To get the most of this section, it's recommended to have read about
read about [commands](/docs/architecture/command), and optionally [commands](/docs/architecture/command), and optionally
[minimodes](/docs/architecture/minimode). [minimodes](/docs/architecture/minimode).
[]($section.id("anatomy"))
## Defining the palette ## Defining the palette
Palettes are under `tui/overlay` and use the facilities offered by Palettes are under `tui/overlay` and use the facilities offered by
@ -43,11 +38,12 @@ Palettes are under `tui/overlay` and use the facilities offered by
2. Filtering the elements 2. Filtering the elements
3. Perform an action with the selected element 3. Perform an action with the selected element
Note: Palettes are meant to show options and allowing to select Note: Palettes are meant to show options and allowing to select the
the options to execute an action on the given selection. To options to execute an action on the given selection. To maintain as
maintain as readable as possible the code and thus extensible, readable as possible the code and thus extensible, the data to be used
the data to be used should be prepared previously. should be prepared previously.
[]($section.id("basic"))
### Fields ### Fields
Basic fields that give hints to the user and need to be set are: Basic fields that give hints to the user and need to be set are:
@ -59,10 +55,11 @@ pub const description = "clipboard";
pub const icon = " "; pub const icon = " ";
``` ```
[]($section.id("entries"))
### Defining the list of elements in the palette ### Defining the list of elements in the palette
`load_entries` is in charge of populating the visible entries, `load_entries` is in charge of populating the visible entries, each one
each one with an index. with an index.
```zig ```zig
pub fn load_entries(palette: *Type) !usize pub fn load_entries(palette: *Type) !usize
@ -70,10 +67,10 @@ pub fn load_entries(palette: *Type) !usize
The index will identify the action to be taken. The index will identify the action to be taken.
When populating with each entry, there must be a relation that When populating with each entry, there must be a relation that links the
links the option chosen with the required action, and this happens option chosen with the required action, and this happens in
in `add_menu_entry` used when the user writes in the input to filter `add_menu_entry` used when the user writes in the input to filter out
out options. options.
```zig ```zig
pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !void { pub fn add_menu_entry(palette: *Type, entry: *Entry, matches: ?[]const usize) !void {
@ -86,25 +83,36 @@ selected item is
try palette.menu.add_item_with_handler(value.written(), select); try palette.menu.add_item_with_handler(value.written(), select);
``` ```
[]($section.id("select"))
### Acting on selection ### Acting on selection
When the selection happens, it is time to invoke the command with the When the selection happens, it is time to invoke the command with the
selection and the palette needs to be closed. selection and the palette needs to be closed. Those actions will be
Those actions will be handled inside `select`, whose signature is: handled inside `select`, whose signature is:
```zig ```zig
fn select(menu: **Type.MenuType, button: *Type.ButtonType, pos: Type.Pos) void { fn select(menu: **Type.MenuType, button: *Type.ButtonType, pos: Type.Pos) void {
``` ```
Other common operations in the palettes can be inspected looking at the source Other common operations in the palettes can be inspected looking at the
code of the palettes, all of them import `palette.zig`. Once the functions are source code of the palettes, all of them import `palette.zig`. Once the
ready, it's time to make the palette available as a command. are ready, it's time to make the palette available as a command.
[]($section.id("register"))
## Registering the palette ## Registering the palette
Commands that open the palette are defined in `tui.zig` in a similar way as it Commands that open the palette are defined in `tui.zig` in a similar way
is done with [minimodes](/docs/architecture/minimode). We have got it is done with [minimodes](/docs/architecture/minimode). We have got
you covered if in doubt about [how to create a command](/docs/architecture/command). you covered if in doubt about
[how to create a command](/docs/architecture/command).
To view a complete implementation of a palette, take a look at To view a complete implementation of a palette, take a look at
[clipboard history palette commit](https://github.com/neurocyte/flow/commit/634a18cb5685a3c3fcfc08301306e628d33c3256) [clipboard history palette commit](https://github.com/neurocyte/flow/commit/634a18cb5685a3c3fcfc08301306e628d33c3256)
[]($section.id("next"))
## Next steps
* [Minimodes](/docs/architecture/minimode)
* [Editor topics](/docs/architecture/editor)
* [On commands](/docs/architecture/command)
* [Architecture](/docs/architecture)

View file

@ -4,65 +4,64 @@
.author = "Igor Támara", .author = "Igor Támara",
.layout = "tutorial.shtml", .layout = "tutorial.shtml",
.draft = false, .draft = false,
.custom = { .githubedit = "https://github.com/neurocyte/flow-website/tree/master/content/docs/mode/helix.md"}, .custom = {
.githubedit = "/docs/mode/helix.smd",
.codepath = "src/tui/mode/helix.zig",
},
--- ---
This document describes implementation of Helix Mode. This document describes implementation of Helix Mode.
## What and what not ## What and what not
The first and biggest difference is that Flow has a mode that The first and biggest difference is that Flow has a mode that emulates
emulates Helix, or at least has equivalent of the worthiest Helix, or at least has equivalent of the worthiest actions that can be
actions that can be done in Helix. The conversely is not true. done with Helix. The conversely is not true.
`:` opens up Flow's rich command palette that might have `:` opens up Flow's rich command palette that might have
functionalities Helix users are used to have, if you find functionalities Helix users are used to have, if you find something
something missing, it's possible to missing, it's possible to
[open a Feature Request](https://github.com/neurocyte/flow/issues), [open a Feature Request](https://github.com/neurocyte/flow/issues),
make sure to review [other issues](https://github.com/neurocyte/flow/issues?q=is%3Aissue%20state%3Aopen%20label%3Ahelix-mode) make sure to review
to avoid repeating or see if there is anyone interested [other issues](https://github.com/neurocyte/flow/issues?q=is%3Aissue%20state%3Aopen%20label%3Ahelix-mode)
in porting on [Discord](https://discord.gg/kzJC9fA7) to ask to avoid repeating or see if there is anyone interested in porting on
if or there is a workaoround, remember that it's possible [Discord](https://discord.gg/kzJC9fA7) to ask if or there is a
to bounce back to Flow mode if needed. workaoround, remember that it's possible to bounce back to Flow mode
if needed.
## Enhancing hx mode ## Enhancing hx mode
This is a programmer editor, you are more than welcome to This is a programmer editor, you are more than welcome to enhance to
enhance to suit your needs that maybe coincide with others. suit your needs that maybe coincide with others.
Please take a look at [architecture](/docs/architecture) and Please take a look at [architecture](/docs/architecture) and
[contributing](/docs/contributing) for an overview and the [contributing](/docs/contributing) for an overview and the mechanics
mechanics of getting your changes into Flow. of getting your changes into Flow.
hx mode is modal kind, the same as vim mode, and the file hx mode is modal kind, the same as vim mode, and the file that has the
that has the particular work to make it real is in particular work to make it real is in `src/tui/mode/helix.zig`, adding
`src/tui/mode/helix.zig`, adding a `command` and the a `command` and the corresponding `meta` is what is required.
corresponding `meta` is what is required.
[More on commands](/docs/architecture/command). [More on commands](/docs/architecture/command).
### Pickers ### Pickers
Flow hx mode offers most of the picker types equivalents Flow hx mode offers most of the picker types equivalents with `panels`
with `panels` and `palettes`. Example of panels are and [palettes](/docs/architecture/palette). Example of panels are
the `g` `r` (go to reference from lsp) and `space` `/` the `g` `r` (go to reference from lsp) and `space` `/` (a.k.a find in
(a.k.a find in files). Examples of `palettes` are files). Examples of `palettes` are `space` `b` to pick a buffer or
`space` `b` to pick a buffer or `space` `f` to open a `space` `f` to open a file in your project. Panels open below the
file in your project. Panels open below the editor editor while palettes open overlapping the working area.
while palettes open overlapping the working area.
One medium sized project is to create a widget that One medium sized project is to create a widget that has one input
has one input widget, two panels, on the left the widget, two panels, on the left, the list of options and, on the right,
list of options and on the right the preview of the preview of the selected option and offer various keybindings to
the selected option and offer various keybindings manipulate the objects inside both panels with filtering.
to manipulate the objects inside both panels with
filtering.
Given this, it's possible to start contributing via Said all of this, it's possible to start contributing via pull
pull requesting [keybinds](/docs/architecture/keybind), requesting [keybinds](/docs/architecture/keybind),
[commands](/docs/architecture/command), [commands](/docs/architecture/command),
[palettes](/docs/architecture/palette), or the [palettes](/docs/architecture/palette), or the special widget
special widget mentioned previously. mentioned previously.
More about the [architecture](/docs/architecture) or jump to More about the [architecture](/docs/architecture) or jump to
[contribution guidelines](/docs/contributing). [contribution guidelines](/docs/contributing).

View file

@ -5,7 +5,7 @@
.layout = "tutorial.shtml", .layout = "tutorial.shtml",
.draft = false, .draft = false,
.custom = { .custom = {
.githubedit = "/docs/testing.md", .githubedit = "/docs/testing.smd",
.codepath ="test", .codepath ="test",
}, },
--- ---