Compare commits

...

4 commits

Author SHA1 Message Date
77b458d4c2
devlog: textDocument/documentSymbol 2025-11-19 10:54:10 +01:00
Igor Támara
7f53e5f523 Added more links to editor 2025-11-19 10:53:11 +01:00
Igor Támara
66bd859993 Add editor and helix to toc and internal links 2025-11-19 10:53:11 +01:00
Igor Támara
7a61aa499e content: editor paraphrased and added internal links 2025-11-19 10:53:11 +01:00
7 changed files with 98 additions and 92 deletions

View file

@ -15,6 +15,17 @@ them.
You can [subscribe to this page via RSS]($link.page('devlog').alternative('rss')) and find more You can [subscribe to this page via RSS]($link.page('devlog').alternative('rss')) and find more
devlog entries in the [archive](/devlog/). devlog entries in the [archive](/devlog/).
## [textDocument/documentSymbol]($section.id("2025-11-19T10:39:21+01:00"))
Flow now has a symbol browser for the current document based on the LSP `textDocument/documentSymbol`
request. Open it in flow mode with `ctrl+shift+\`. As usual the list can be filtered with a fuzzy
query. Navigating in the list will preview the location of the symbol in the document. Selecting
a symbol will jump to it. The preview function is nice to quickly view another symbol without
jumping away for your current file location.
[]($image.asset('2025-11-19.png'))
## [centered view]($section.id("2025-11-17T20:56:38+01:00")) ## [centered view]($section.id("2025-11-17T20:56:38+01:00"))
For very wide screens you can now center the view with `ctrl+k x`, or the command For very wide screens you can now center the view with `ctrl+k x`, or the command

Binary file not shown.

After

Width:  |  Height:  |  Size: 620 KiB

View file

@ -11,9 +11,9 @@
--- ---
Commands are actions triggered to operate on buffers primarily. They are Commands are actions triggered to operate on buffers primarily. They are
present in `editor`, `tui`, `mode` and `minimodes`, it's possible to present in [editor](/docs/architecture/editor), `tui`, `mode` and
find commands in other places, which will become evident when the need `minimodes`, it's possible to find commands in other places, which
arises. will become evident when the need arises.
## Previous notes[]($section.id('notes')) ## Previous notes[]($section.id('notes'))
@ -160,6 +160,11 @@ pub fn select_to_char_left_helix(_: *void, ctx: Ctx) Result {
## [Next steps]($section.id('next')) ## [Next steps]($section.id('next'))
[Editor](/docs/architecture/editor) has a walkthrough when working with
selections, modifying the contents of the editor and deepens in concepts
that allow understand how the internal interactions happen when editing
a document.
[Minimodes](/docs/architecture/minimode) pass arguments to the editor, [Minimodes](/docs/architecture/minimode) pass arguments to the editor,
if you wonder how to go beyond the current buffer window, when there if you wonder how to go beyond the current buffer window, when there
are actions like going to a specific line or when searching or are actions like going to a specific line or when searching or

View file

@ -16,42 +16,38 @@ To get the most of this section, it's recommended to have read the
[keybinds](/docs/architecture/keybind) at least. [keybinds](/docs/architecture/keybind) at least.
A word of warning: Flow code evolves and it is possible that some code A word of warning: Flow code evolves and it is possible that some code
exposed here is older than the current one. Always refer to exposed here is older than the current one. If in doubt, always refer to
[master](https://github.com/neurocyte/flow) in doubt. [master](https://github.com/neurocyte/flow).
[]($section.id("concepts")) ## [Some concepts]($section.id("concepts"))
## Some concepts
The [editor](#editor_concept) coordinates visualization and The [editor](#editor_concept) coordinates visualization and
modification of buffer contents, multiple cursors, selections and modification of buffer contents, multiple [cursors](#cursor_concept),
marks. [selections](#selection_concept) and [marks](#mark_concept).
We will delve in editor concepts, buffer inner manipulation with ropes We will delve in editor concepts, buffer inner manipulation with ropes
is not covered here. is not covered here.
[]($section.id("tui_editor")) ### [Editor and TUI]($section.id("tui_editor"))
### Editor and TUI
During this section we will refer to the concept of the editor as the During this section we will refer to the concept of the editor as the
one capable of modifying buffer contents, the visible gutters and one capable of modifying buffer contents, the visible gutters and
line numbers as other terminal user interface (TUI) is covered in line numbers as other terminal user interface (TUI) is covered in
another chapter. another chapter.
[]($section.id("view_concept")) ### [View]($section.id("view_concept"))
### View
`View` holds the information about the area of the buffer that is `View` holds the information about the area of the buffer that is
currently visible in the screen by the user. Is related to the currently visible in the screen by the user. Is related to the
[primary cursor](#cursor_concept). [primary cursor](#cursor_concept).
[]($section.id("cursor_concept")) ### [Cursor]($section.id("cursor_concept"))
### Cursor
The `primary Cursor` holds a position in the Buffer, the `Editor` The `primary Cursor` holds a position in the Buffer, the `Editor`
makes the link between both of them, signaling the part of the `Buffer` makes the link between both of them, signaling the part of the `Buffer`
that can be modified and manipulated as you see it. It scrolls on the that can be modified and manipulated as you see it. It scrolls on the
current visible portion [view](#view_concept) of the buffer, when current visible portion [view](#view_concept) of the buffer, when
manipulated with the keyboard, the mouse can change the move the view manipulated with the keyboard, the mouse on its own can move the view
while the primary mouse is off-screen; when keystrokes arrive to the while the primary mouse is off-screen; when keystrokes arrive to the
editor, the view focuses to the primary cursor to make it visible and editor, the view focuses to the primary cursor to make it visible and
available to be used. available to be used.
@ -67,10 +63,9 @@ Cursors visibility depends on the size of both the buffer contents and
the editor in your device. the editor in your device.
Most of editors operations act on the set of CurSels and the Primary Most of editors operations act on the set of CurSels and the Primary
Cursor is a [CurSel](#cursel_concept). Cursor is really a [CurSel](#cursel_concept).
[]($section.id("selection_concept")) ### [Selection]($section.id("selection_concept"))
### Selection
A selection is represented by begin and end [cursors](#cursor_concept) A selection is represented by begin and end [cursors](#cursor_concept)
and offers basic functions that will constitute the changes needed with and offers basic functions that will constitute the changes needed with
@ -80,31 +75,25 @@ services and [commands](/docs/architecture/command).
A `Selection` has two cursors that are not visible, they mark the begin A `Selection` has two cursors that are not visible, they mark the begin
and the end of the selection. and the end of the selection.
### [CurSel]($section.id("cursel_concept"))
[]($section.id("cursel_concept"))
### CurSel
The CurSel is what is presented to user, holding a The CurSel is what is presented to user, holding a
[cursor](#cursor_concept) and optionally a [cursor](#cursor_concept) and optionally a
[selection](#selection_concept). [selection](#selection_concept) which allows to have the concept of a
cursor with a selection.
### [Mark]($section.id("mark_concept"))
[]($section.id("mark_concept"))
### Mark
what allow to have the concept of a cursor with a selection. A `Cursel`
is composed by a cursor and optionally a Selection.
To complete the editor scenario, `Marks` have the potential to become To complete the editor scenario, `Marks` have the potential to become
selections; the marks become evident to the eye when in search mode, selections; the marks become evident to the eye when in search mode,
they are seen as the primary cursor is positioned over an occurrence they are seen as the primary cursor is positioned over an occurrence
with a different color according to the theme. with a different color according to the theme.
[]($section.id("editor_concept")) ### [Editor]($section.id("editor_concept"))
### Editor
The Editor will be acting on Buffer.Root which is the root of the tree The Editor will be acting on Buffer.Root which is the root of the tree
representing the document that is being edited. API Buffer.Root is representing the document that is being edited. API Buffer.Root is
stable and offers the necessary to insert, delete and move along the stable and offers the necessary to insert, delete and move along the
buffer, knowing if the end or the beginning of the document have been buffer, knowing if the end or the beginning of the document has been
reached when interacting with a Cursor. reached when interacting with a Cursor.
Cursors, Selections and Cursels don't know about the buffer, and they Cursors, Selections and Cursels don't know about the buffer, and they
@ -113,15 +102,14 @@ restrictions and usually receive `metrics` from the editor that help
determine if a cursor is about to exit the boundaries of the buffer determine if a cursor is about to exit the boundaries of the buffer
and be inside bounds. and be inside bounds.
[]($section.id("commands")) ## [Editor Commands]($section.id("commands"))
## Editor Commands
We mentioned earlier that most of the operations work on all the We mentioned earlier that most of the operations work on all the
cursors and selections, moreover, there are various commands acting cursors and selections, moreover, there are various commands acting
over the set of cursors, selections, cursels or marks. Given said over the set of cursors, selections, cursels or marks. Given said
this, we will be using functions as parameters in most of the this, we will be using functions as parameters in most of the
situations. Functional programming languages are popular in these situations. Functional programming languages are popular in these
scenarios, to name a prominent one, Emacs and emacs lisp. Flow is scenarios, to name a prominent one, emacs lisp from Emacs. Flow is
inspired on it and others. inspired on it and others.
If the buffer is not to be modified, we will be using the method If the buffer is not to be modified, we will be using the method
@ -135,10 +123,10 @@ functionalities, because one would be thinking only in the current
cursor and if required, the operation will be applied to all the cursor and if required, the operation will be applied to all the
cursors, the same applies to selections, cursels and marks. cursors, the same applies to selections, cursels and marks.
[]($section.id("moving")) ## [Moving]($section.id("moving"))
## Moving
For example, to move the cursors a page up, we can look at the command For example, to move the cursors a page up, we can look at the
[command](/docs/architecture/command)
`move_page_up`, `move_page_up`,
>[]($block.attrs('line-numbers-js')) >[]($block.attrs('line-numbers-js'))
@ -171,8 +159,8 @@ Looking inside `with_cursors_and_view_const`
>``` >```
It iterates over all the cursors and invokes It iterates over all the cursors and invokes
`with_cursor_and_view_const`, sending the `move` function, a cursor, `with_cursor_and_view_const`, sending the `move` function, a cursor;
remember that the function passed was `move_cursor_page_up` as seen remember that the function passed was `move_cursor_page_up` as shown
previously. previously.
The commitment of `move_cursor_page_up` is to use the method The commitment of `move_cursor_page_up` is to use the method
@ -185,11 +173,10 @@ fn move_cursor_page_up(root: Buffer.Root, cursor: *Cursor, view: *const View, me
``` ```
The `move` functions set is numerous, look for the methods whose name The `move` functions set is numerous, look for the methods whose name
have the word `move` in them. with the command palette is possible to get have the word `move` in them. With the command palette is possible to get
a glimpse of the available functions present(ctrl+f2). a glimpse of the available functions present(ctrl+f2).
[]($section.id("selecting")) ## [Selections]($section.id("selecting"))
## Selections
Function naming conventions help understand the purpose of each one, Function naming conventions help understand the purpose of each one,
there has been taken great deal of care to maintain consistency, it's there has been taken great deal of care to maintain consistency, it's
@ -209,6 +196,7 @@ pub fn select_up(self: *Self, ctx: Context) Result {
} }
pub const select_up_meta: Meta = .{ .description = "Select up", .arguments = &.{.integer} }; pub const select_up_meta: Meta = .{ .description = "Select up", .arguments = &.{.integer} };
``` ```
It's meta is guiding about the integer argument that the command can It's meta is guiding about the integer argument that the command can
make use of. Invokes `with_selections_const_repeat` passing the make use of. Invokes `with_selections_const_repeat` passing the
function `move_cursor_up` as parameter and also the context, which function `move_cursor_up` as parameter and also the context, which
@ -238,12 +226,14 @@ the `while`, then for each repetition, the set of cursels is iterated,
cursels hold cursors and selections, applying `with_selection_const` cursels hold cursors and selections, applying `with_selection_const`
function, passing `root`(the buffer), `move_cursor_up` function, cursel function, passing `root`(the buffer), `move_cursor_up` function, cursel
and metrics as parameters. Note that after the function is applied to and metrics as parameters. Note that after the function is applied to
each cursel, self.collapse_cursors() is invoked, given that it's each cursel, `self.collapse_cursors()` is invoked, given that it's
possible that some cursors in the operation have overlapped. With each possible that some cursors in the operation have overlapped.
cursel operation there is also a tracking of possible fails, continuing
gracefully, one of such fails can be happening because come cursels With each cursel operation there is also a tracking of possible fails,
might have been reaching the beginning of the buffer and there might be continuing gracefully, one of such fails can be happening because some
other cursels that have not yet reached the beginning of the file. cursels might have been reaching the beginning of the buffer and there
might be other cursels that have not yet reached the beginning of the
file.
```zig ```zig
pub fn with_selection_const(root: Buffer.Root, move: cursor_operator_const, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void { pub fn with_selection_const(root: Buffer.Root, move: cursor_operator_const, cursel: *CurSel, metrics: Buffer.Metrics) error{Stop}!void {
@ -264,12 +254,12 @@ applied with its method `check_selection`.
Flow allows navigating the code with `goto_definition` and `references` Flow allows navigating the code with `goto_definition` and `references`
commands to deepen the understanding and following the different calls. commands to deepen the understanding and following the different calls.
[]($section.id("modifying")) ## [Modifying the buffer]($section.id("modifying"))
## 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`
functions, in contrast, the `cut`, `delete`, `insert`, `paste` looks functions, in contrast, the `cut`, `delete`, `insert`, `paste` set
smaller, and this is accomplished making composition of functions. looks smaller, and this is accomplished making composition of functions.
Usually when modifying something, first there is a process to locate Usually when modifying something, first there is a process to locate
the cursor, cursel or selection in the proper place and then applying the cursor, cursel or selection in the proper place and then applying
the modification. There are cases when there is need to locate and the modification. There are cases when there is need to locate and
@ -277,7 +267,7 @@ act right away.
When additions, changes and removal of buffer contents, editor offers When additions, changes and removal of buffer contents, editor offers
the method `buf_for_update`; we will look first to the method the method `buf_for_update`; we will look first to the method
`to_upper_cursel`, which by default in Flow, takes a CurSel, if it has `to_upper_cursel`, which by default in Flow, takes a CurSel; if it has
no selection, the word that it is stepped on, if any, is selected and no selection, the word that it is stepped on, if any, is selected and
gets uppercased. gets uppercased.
@ -332,10 +322,10 @@ pub fn to_upper(self: *Self, _: Context) Result {
pub const to_upper_meta: Meta = .{ .description = "Convert selection or word to upper case" }; pub const to_upper_meta: Meta = .{ .description = "Convert selection or word to upper case" };
``` ```
via `with_cursels_mut_once` receives a buffer that will be modified `with_cursels_mut_once` receives a buffer that will be modified
and returns one with modifications, updating what is presented with and returns one with modifications, updating what is presented with
the method `update_buf` and an allocator. The previously described the method `update_buf` and an allocator. The previously described
`to_upper_cursel` is sent function `to_upper_cursel` is sent
>[]($block.attrs('line-numbers-js')) >[]($block.attrs('line-numbers-js'))
>```zig >```zig
@ -357,9 +347,10 @@ Worth to note that the modified `root` is being passed to the function
`with_cursel_mut` on each iteration over the cursels along with the `with_cursel_mut` on each iteration over the cursels along with the
allocator and as described previously in selection functions, tracking allocator and as described previously in selection functions, tracking
if there is some fail an error is popped up, whilst everything was if there is some fail an error is popped up, whilst everything was
successful, the modified `root` is returned. Now time to see the successful, the modified `root` is returned.
method `with_cursel_mut` that receives the pointer to `to_upper_cursel`
along with root, cursel and allocator. Now time to see the method `with_cursel_mut` that receives the pointer
to `to_upper_cursel` along with root, cursel and allocator.
```zig ```zig
fn with_cursel_mut(self: *Self, root: Buffer.Root, op: cursel_operator_mut, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root { fn with_cursel_mut(self: *Self, root: Buffer.Root, op: cursel_operator_mut, cursel: *CurSel, allocator: Allocator) error{Stop}!Buffer.Root {
@ -370,17 +361,17 @@ fn with_cursel_mut(self: *Self, root: Buffer.Root, op: cursel_operator_mut, curs
As seen, the only task for `with_cursel_mut` is providing the required As seen, the only task for `with_cursel_mut` is providing the required
elements to let `to_upper_cursel` do what was described previously. elements to let `to_upper_cursel` do what was described previously.
## Adding functionalities to the editor ## [Adding functionalities to the editor]($section.id("adding"))
As shown, the basics to manipulate the buffer via the editor involves As shown, the basics to manipulate the buffer via the editor involves
reviewing if cursors, marks, selections are to be modified, changed or reviewing if cursors, marks, selections are to be modified, changed or
if the contents are. Picking functions for it and focusing on the if the contents are. Picking functions for it and focusing on the
task for a single cursel, cursor or selection is key and the use of the task for a single cursel, cursor or selection is key and the use of the
already present functions will allow to act on multiple elements at already present functions will allow to act on multiple elements at
once. once. By convention functions with name `mut` will modify the buffer while
`const` will not.
[]($section.id("next")) ## [Next steps]($section.id("next"))
## Next steps
* [minimodes](/docs/architecture/minimode) invoke * [minimodes](/docs/architecture/minimode) invoke
[commands](/docs/architecture/minimode) defined in the editor [commands](/docs/architecture/minimode) defined in the editor

View file

@ -43,18 +43,27 @@ offers services around the set of projects.
## [Editor commands and modes]($section.id("commands")) ## [Editor commands and modes]($section.id("commands"))
When a buffer is active, it has an Editor When a buffer is active, it has an Editor
attached to it; an editor might have associated tree-sitter support, attached to it; an [editor](/docs/architecture/editor) might have
given the file type detected, and offers common services that are aimed associated tree-sitter support, given the file type detected, and
to be used by `Commands` to manipulate the contents of a buffer at a offers common services that are aimed to be used by `Commands` to
higher level, the selections, cursors, cursor selections `CurSel` and manipulate the contents of a buffer at a higher level, the
the `View`. [Commands](/docs/architecture/command) are used by `Modes` [selections](/docs/architecture/editor#selection_concept),
[cursors](/docs/architecture/editor#cursor_concept),
cursor selections
([CurSel](/docs/architecture/editor#cursel_concept)),
[markers](/docs/architecture/editor#mark_concept) and the
[view](/docs/architecture/editor#view_concept).
[Commands](/docs/architecture/command) are used by `Modes`
with [Keybindings](/docs/architecture/keybind). The main mode is Flow with [Keybindings](/docs/architecture/keybind). The main mode is Flow
and the keybindings can be used to map to a mode built up entirely on and the keybindings can be used to map to a mode built up entirely on
solely calling already created commands. An example of a mode solely calling already created commands.
created by command composition is `Emacs` mode, for instance, it's
possible to create a nano mode with just keybindings. In the other hand, An example of a mode created by command composition is `Emacs` mode,
`Vim` and [Helix](/docs/mode/helix) modes have particular definitions for instance, it's possible to create a nano mode with just keybindings.
for commands that interact with the buffers, being modal editors. In the other hand, `Vim` and [Helix](/docs/mode/helix) modes have
particular definitions for commands that interact with the buffers,
being modal editors.
## [Text user interface]($section.id("tui")) ## [Text user interface]($section.id("tui"))

View file

@ -12,8 +12,7 @@
This document describes Helix Mode implementation. This document describes Helix Mode implementation.
[]($section.id('what')) ## [What and what not]($section.id('what'))
## What and what not
The first and biggest difference is that Flow has a mode that emulates The first and biggest difference is that Flow has a mode that emulates
Helix, or at least has equivalent of the worthiest actions that can be Helix, or at least has equivalent of the worthiest actions that can be
@ -31,12 +30,11 @@ make sure to review
[other issues](https://github.com/neurocyte/flow/issues?q=is%3Aissue%20state%3Aopen%20label%3Ahelix-mode) [other issues](https://github.com/neurocyte/flow/issues?q=is%3Aissue%20state%3Aopen%20label%3Ahelix-mode)
to avoid repeating or see in [Discord](https://discord.gg/kzJC9fA7) to avoid repeating or see in [Discord](https://discord.gg/kzJC9fA7)
to ask if there is a workaround, or anyone else is interested in to ask if there is a workaround, or anyone else is interested in
porting your requirement, adding a reaction to an issue offers porting your requirement; adding a reaction to an issue offers
awareness on what to implement or to get higher priority, remember that awareness on what to implement or to get higher priority, remember that
it's possible to bounce back to Flow(f4) mode if needed. it is possible to bounce back to Flow(f4) mode if needed.
[]($section.id('enhancing')) ## [Enhancing hx mode]($section.id('enhancing'))
## Enhancing hx mode
This is a programmer's editor, you are more than welcome to enhance to This is a programmer's editor, you are more than welcome to enhance to
suit your needs that maybe coincide with others. suit your needs that maybe coincide with others.
@ -50,8 +48,7 @@ particular work to make it real is `src/tui/mode/helix.zig`, adding
a `command` and the corresponding `meta` is what is required. a `command` and the corresponding `meta` is what is required.
[More on commands](/docs/architecture/command). [More on commands](/docs/architecture/command).
[]($section.id('pickers')) ### [Pickers]($section.id('pickers'))
### Pickers
Flow hx mode offers most of the Helix pickers functionalities with Flow hx mode offers most of the Helix pickers functionalities with
`panels` and [palettes](/docs/architecture/palette). Example of panels `panels` and [palettes](/docs/architecture/palette). Example of panels
@ -60,20 +57,12 @@ in files). Examples of `palettes` are `space` `b` to pick a buffer or
`space` `f` to open a file in your project. Panels open below the `space` `f` to open a file in your project. Panels open below the
editor while palettes open overlapping the working area. editor while palettes open overlapping the working area.
One medium sized project is to create a **Helix picker** widget that ## [Next steps]($section.id('next'))
has one input widget with two panels, on the left, the list of options
and, on the right, the preview of the selected option. The input
widget reacts to various keybindings to manipulate the objects inside
both panels with filtering. `src/tui/mode/overlay/palette.zig`
implements much of the required functionality.
[]($section.id('next'))
## Next steps
Said all of this, it's possible to start contributing via pull Said all of this, it's possible to start contributing via 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 **hx picker**. [palettes](/docs/architecture/palette), or anything you wish were here.
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

@ -18,14 +18,15 @@
<ul> <ul>
<li><a href="$site.page('docs/contributing').link()">contributing</a></li> <li><a href="$site.page('docs/contributing').link()">contributing</a></li>
<li><a href="$site.page('docs/testing').link()">testing</a></li> <li><a href="$site.page('docs/testing').link()">testing</a></li>
<li><a href="$site.page('docs/architecture').link()">architeture</a></li> <li><a href="$site.page('docs/architecture').link()">architecture</a></li>
<li><ul> <li><ul>
<li><a href="$site.page('docs/architecture/keybind').link()">keybind</a></li> <li><a href="$site.page('docs/architecture/keybind').link()">keybind</a></li>
<li><a href="$site.page('docs/architecture/command').link()">command</a></li> <li><a href="$site.page('docs/architecture/command').link()">command</a></li>
<!-- <li><a href="$site.page('docs/architecture/editor').link()">editor</a></li> --> <li><a href="$site.page('docs/architecture/editor').link()">editor</a></li>
<li><a href="$site.page('docs/architecture/minimode').link()">minimode</a></li> <li><a href="$site.page('docs/architecture/minimode').link()">minimode</a></li>
<li><a href="$site.page('docs/architecture/palette').link()">palette</a></li> <li><a href="$site.page('docs/architecture/palette').link()">palette</a></li>
<li><a href="$site.page('docs/architecture/inner_data_exchange').link()">exchanging data</a></li></ul></li> <li><a href="$site.page('docs/architecture/inner_data_exchange').link()">exchanging data</a></li></ul></li>
<li><a href="$site.page('docs/mode/helix').link()">hx mode</a></li>
<li><a href="https://deepwiki.com/neurocyte/flow" target="_alt">deepwiki</a></li> <li><a href="https://deepwiki.com/neurocyte/flow" target="_alt">deepwiki</a></li>
</ul> </ul>
</div> </div>