Ensure that the selection start is always before the selection end,
regardless of the direction of a mouse selection, to make
h.Cursor.Deselect() handle its `start` argument correctly.
This makes the cursor behavior after mouse selections consistent with
the cursor behavior after keyboard selections.
Fixes#3055
Previously `CursorDown` function called `Deselect` with a wrong
argument which lead to the situation when cursor was moved to the
start instead of the end of the selection
Signed-off-by: Yevhen Babiichuk (DustDFG) <dfgdust@gmail.com>
Fix the following buggy behavior:
1. bind "<n><a>" to the Paste action in the command bar
2. open a split pane, type some text and press Ctrl-q to close it
3. answer "n" to the "Save changes before closing?" prompt
4. press Ctrl-e to open the command prompt and press "a"
-> result: instead of inserting the "a" letter, clipboard is pasted.
It is not really defined what is the meaning of this return value.
Currently this value is always true. And even if this value actually
meant something (for example, the result of the last executed action
in the chain), we should not use this value in HandleEvent(). The key
event handling logic should behave the same regardless of whether the
action triggered by this key succeeded or not.
If onBufPaneOpen callback execution fails (e.g. due to a Lua runtime
error), report this error to the user, like we do for all other Lua
callbacks, rather than silently continue working as if nothing
happened.
After reloading a file that has been externally modified, the buffer
view may become invalid: the displayed subset of lines of the file may
no longer exist, since the file may have been truncated. So relocate the
buffer view in this case.
In particular, this fixes crashes caused by out of bounds accesses to
the line array by displayBuffer() trying to display no longer existing
lines.
Currently onSetActive is called when the user clicks with the mouse on
a pane even if this pane is already active. We should avoid calling it
in this case.
Implementation detail: like with tabs in the previous commit, we cannot
check if the pane is already active just by checking the index passed
to the Tab's SetActive() (since the index may not change while the pane
itself changes), we need to check state of the pane itself. So we move
the onSetActive invocation from the Tab's SetActive() to the BufPane's
SetActive().
We should call the onSetActive callback not only when switching to
another bufpane within the same tab but also when switching to another
tab.
Note on implementation details:
- In SetActive() we need to check if the tab is not already active, to
avoid calling onSetActive for an already active bufpane.
- We cannot check that just by checking if the tab index passed to
SetActive() is different from the current active tab index, since this
index may remain the same even if the tab itself is different (in the
case of removing a tab from the tablist). So we need to check the tab
itself, not just the tab index. So we introduce the isActive field,
to track the tab's active state in the Tab structure itself.
* infocomplete: Complete filetypes (follow-up)
The first shot of the feature unfortunately completed the *.yaml file
names instead of the included filetypes. This will be corrected with
this follow up.
* infocomplete: Correct comment of filetypeComplete according to review hint
Co-authored-by: Dmytro Maluka <dmitrymaluka@gmail.com>
---------
Co-authored-by: Dmytro Maluka <dmitrymaluka@gmail.com>
`unknown` is a valid value for the `filetype` option (and executing
`set filetype unknown` does what is expected: it forces filetype
autodetection). So let's add `unknown` to the autocomplete suggestions
for `filetype`, along with actual filetypes.
* rtfiles: Initialize all-/realFiles and Plugins in InitRuntimeFiles
* command: Reload plugins at ReloadCmd too
* command: Don't reload plugins in case of ReloadConfig()
* rtfiles: Split InitRuntimeFiles() into one func for assets and one for plugins
* rtfiles: Remove the unnecessary init function
With this modification the InitRuntimeFiles() and InitPlugins() (if needed)
must be called first, otherwise uninitialized runtime file variables are most
likely.
InfoBar should really receive the resize event, to know the window width
in order to do horizontal scrolling of the command line when it doesn't
fit in the screen. Although currently it doesn't scroll the command line
at all (see issue #2527) and just ignores the resize event, but we
should fix that anyway, so let's forward the resize event to it.
* command: Fix replace to be able to insert '$'
* help: commands: Precise the documentation of `replace`
* help: commands: Further improvement suggested within the review
Co-authored-by: Beni Cherniavsky-Paskin <cben@redhat.com>
* Fix replace with '$' in a more kosher way
On top of JoeKar's fix.
---------
Co-authored-by: Beni Cherniavsky-Paskin <cben@redhat.com>
Co-authored-by: Dmytro Maluka <dmitrymaluka@gmail.com>
* settings: Move all options to the start of the file
This will help with the overview of all available options and their optional
validators.
* settings: Add generic string option validator
* settings: Autocomplete string options
Passing options via micro -option=value in the command line should only
temporarily override the option value for the current micro session,
not change it permanently in settings.json. But currently it wrongly
writes it to settings.json in the case when the value passed via command
line is the default value of this option, while the current permanent
setting in settings.json is a non-default value.
Fixes#3005
If we add something like this to init.lua:
config.AddRuntimeFile("status", config.RTHelp, "help/foo.md")
then start micro and run "help foo", the resulting error message looks
weird:
Unable to load help textfooopen plugins/status/help/foo.md: file does not exist
Change it to:
Unable to load help text for foo: open plugins/status/help/foo.md: file does not exist
- If a mouse event is bound to a Lua function, pass *tcell.EventMouse to
this Lua function, so that it can find out the position where a button
was clicked etc, just like the built-in MousePress and MouseMultiCursor
actions.
- Make mouse actions more a first-class citizen: allow chaining them and
running onAction and preAction callbacks for them, just like key actions.
Improve user experience: if we are at a line with a new (i.e.
not highlighted yet) trailingws and we begin selecting text,
don't highlight the trailingws until we are done with selection,
even if we moved the cursor to another line while selecting.
Added option `hltrailingws` for highlighting trailing whitespaces
at the end of lines. Note that it behaves in a "smart" way.
It doesn't highlight newly added (transient) trailing whitespaces
that naturally occur while typing text. It would be annoying to
see transient highlighting every time we enter a space at the end
of a line while typing.
So a newly added trailing whitespace starts being highlighting
only after the cursor moves to another line. Thus the highlighting
serves its purpose: it draws our attention to annoying sloppy
forgotten trailing whitespaces.
* Update docs to include `matchbracestyle`
* Add `matchbracestyle` to infocomplete.go
* Add validator and default settings for `matchbracestyle`
* Highlight or underline braces based on `matchbracestyle`
* Add `match-brace` to default colorschemes
* Correct `FindMatchingBrace()` counting
Make brace under the cursor have priority over brace to the left in
ambiguous cases when matching braces
Co-authored-by: Dmitry Maluka <dmitrymaluka@gmail.com>
* Fix conflicts
---------
Co-authored-by: Jöran Karl <3951388+JoeKar@users.noreply.github.com>
Co-authored-by: Dmitry Maluka <dmitrymaluka@gmail.com>
* SpawnMultiCursorUp/Down: change order of adding cursors
SpawnMultiCursor{Up,Down} currently works in a tricky way: instead of
creating a new cursor above or below, it moves the current "primary"
cursor above or below, and then creates a new cursor below or above the
new position of the current cursor (i.e. at its previous position),
creating an illusion for the user that the current (top-most or
bottom-most) cursor is a newly spawned cursor.
This trick causes at least the following issues:
- When the line above or below, where we spawn a new cursor, is shorter
than the current cursor position in the current line, the new cursor
is placed at the end of this short line (which is expected), but also
the current cursor unexpectedly changes its x position and moves
below/above the new cursor.
- When removing a cursor in RemoveMultiCursor (default Alt-p key), it
non-intuitively removes the cursor which, from the user point of view,
is not the last but the last-but-one cursor.
Fix these issues by replacing the trick with a straightforward logic:
just create the new cursor above or below the last one.
Note that this fix has a user-visible side effect: the last cursor is
no longer the "primary" one (since it is now the last in the list, not
the first), so e.g. when the user clears multicursors via Esc key, the
remaining cursor is the first one, not the last one. I assume it's ok.
* SpawnMultiCursorUp/Down: move common code to a helper fn
* SpawnMultiCursorUp/Down: honor visual width and LastVisualX
Make spawning multicursors up/down behave more similarly to cursor
movements up/down. This change fixes 2 issues at once:
- SpawnMultiCursorUp/Down doesn't take into account the visual width of
the text before the cursor, which may be different from its character
width (e.g. if it contains tabs). So e.g. if the number of tabs before
the cursor in the current line is not the same as in the new line, the
new cursor is placed at an unexpected location.
- SpawnMultiCursorUp/Down doesn't take into account the cursor's
remembered x position (LastVisualX) when e.g. spawning a new cursor
in the below line which is short than the current cursor position, and
then spawning yet another cursor in the next below line which is
longer than this short line.
* SpawnMultiCursorUp/Down: honor softwrap
When softwrap is enabled and the current line is wrapped, make
SpawnMultiCursor{Up,Down} spawn cursor in the next visual line within
this wrapped line, similarly to how we handle cursor movements up/down
within wrapped lines.
* SpawnMultiCursorUp/Down: deselect when spawning cursors
To avoid weird user experience (spawned cursors messing with selections
of existing cursors).
It is useful to be able to use mouse not only for adding new cursors
but also for removing them. So let's modify MouseMultiCursor behavior:
if a cursor already exists at the mouse click location, remove it.