189 Commits

Author SHA1 Message Date
Robin Jarry
0211c9bf23 reload: fix crash when reloading via IPC
When reloading the configuration with :reload, global variables in the
config package are reset to their startup values and then, the config is
parsed from disk. While the parsing is done, these variables are
temporarily in an inconsistent and possibly invalid state.

When commands are executed interactively from aerc, they are handled by
the main goroutine which also deals with UI rendering. No UI render will
be done while :reload is in progress.

However, the IPC socket handler runs in an independent goroutine. This
has the unfortunate side effect to let the UI goroutine to run while
config parsing is in progress and causes crashes:

[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x6bb142]

goroutine 1 [running]:
git.sr.ht/~rjarry/aerc/lib/log.PanicHandler()
	lib/log/panic-logger.go:51 +0x6cf
panic({0xc1d960?, 0x134a6e0?})
	/usr/lib/go/src/runtime/panic.go:783 +0x132
git.sr.ht/~rjarry/aerc/config.(*StyleConf).getStyle(0xc00038b908?, 0x4206b7?)
	config/style.go:386 +0x42
git.sr.ht/~rjarry/aerc/config.StyleSet.Get({0x0, 0x0, 0x0, {0x0, 0x0, 0x0}}, 0x421a65?, 0x0)
	config/style.go:408 +0x8b
git.sr.ht/~rjarry/aerc/config.(*UIConfig).GetStyle(...)
	config/ui.go:379
git.sr.ht/~rjarry/aerc/lib/ui.(*TabStrip).Draw(0xc000314700, 0xc000192230)
	lib/ui/tab.go:378 +0x15b
git.sr.ht/~rjarry/aerc/lib/ui.(*Grid).Draw(0xc000186fc0, 0xc0002c25f0)
	lib/ui/grid.go:126 +0x28e
git.sr.ht/~rjarry/aerc/app.(*Aerc).Draw(0x14b9f00, 0xc0002c25f0)
	app/aerc.go:192 +0x1fe
git.sr.ht/~rjarry/aerc/lib/ui.Render()
	lib/ui/ui.go:155 +0x16b
main.main()
	main.go:310 +0x997

Make the reload operation safe by changing how config objects are
exposed and updated. Change all objects to be atomic pointers. Expose
public functions to access their value atomically. Only update their
value after a complete and successful config parse. This way the UI
thread will always have access to a valid configuration.

NB: The account configuration is not included in this change since it
cannot be reloaded.

Fixes: https://todo.sr.ht/~rjarry/aerc/319
Reported-by: Anachron <gith@cron.world>
Signed-off-by: Robin Jarry <robin@jarry.cc>
2025-09-08 12:19:51 +02:00
GregTheMadMonk
d31995f1e2 ui: implement C-left/C-right cursor controls for textinput
When typing inside textinput, Ctrl+Left places the cursor at the start
of the current word, and Ctrl+Right goes to the start of the next one.

Ctrl+Left uses the same code `deleteWord()` function used (which is now
split into a separate function), and Ctrl+Right uses similar lookup in
the other direction.

Implements: https://todo.sr.ht/~rjarry/aerc/231
Signed-off-by: GregTheMadMonk <yagreg7@gmail.com>
Tested-by: skejg <grolleman@zoho.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-30 11:05:30 +02:00
Simon Martin
63e6a018ae grid: fix possible crash on startup due to unsynchronized access
I've encountered a few crashes when starting aerc while also playing
with the mouse; see for instance
  https://paste.sr.ht/~simartin/e71203c56daebec1dd6e96916f88a229d8b41b2b

This is due to a race between Grid.MouseEvent and grid.reflow: the
latter modifies the grid without taking the associated mutex, while it
should.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-06-19 12:23:32 +02:00
Simon Martin
80f3fb4325 ui: update tab title when replacing by with another
When navigating between messages in the Message Viewer, the whole tab is
updated except its title: it remains set to the subject of the message
that was initially opened in that tab.

Tabs.Replace needs to update both the content *and* the title; this is
what this patch does.

Signed-off-by: Simon Martin <simon@nasilyan.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-05-21 18:28:56 +02:00
Karel Balej
f0ec95d7dd account: allow indicating new messages in the tab title
Add a flag to indicate whether the account has received new messages
since it last had focus and allow its use in the templates.

Changelog-added: A `.HasNew` flag indicating whether the account has
 received new messages to be used in the templates.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Tested-by: Inwit <inwit@sindominio.net>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-04-07 10:51:14 +02:00
Robin Jarry
0ca8087ec9 treewide: replace interface{} with any
Since go 1.18, interface{} can be replaced with any.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Karel Balej <balejk@matfyz.cz>
2025-04-07 10:51:05 +02:00
Moritz Poldrack
731b0a2a16 ui: map number block to regular counterparts
Due to vaxis low-level design, the enter key of the number block has
a different key code that a regular carriage return. Since most people
do not care which of the two they are hitting, remap the former and
up/down/left/right to act like the latter.

Changelog-added: Support for number block enter to act as <Cr>
 in mappings.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-03-20 15:15:22 +01:00
Karel Balej
dbe350a585 msgview: add copy-link command
Add a command to copy links to the system clipboard. This can be useful
for instance when the URL should be handled in some other way than
opened (e. g. resent via some other communication channel or saved to a
file). It also improves security for situations where it's not desirable
for the URL to be visible on the process command line, such as when it
contains sensitive information such as an access token.

Adapted from open-link.

Changelog-added: If supported by the terminal, links from a message
 can now be copied to the system clipboard with the :copy-link command
 of the message viewer.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-02-06 13:59:24 +01:00
Robin Jarry
4e545d45fa treewide: fix English spelling
Use codespell to fix typos in code, comments and man pages.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Bence Ferdinandy <bence@ferdinandy.com>
Acked-by: inwit <inwit@sindominio.net>
2025-01-21 13:39:01 +01:00
Karel Balej
fae4a0a1e8 ui: fix the position of the address-book completion popovers
When composing a message, the location of the popovers was not offset by
the location of the field that was being completed (To, Cc,...)
resulting in them appearing always at the same position near the top
left corner of the window. Restore the offset to have them appear right
underneath the active field again.

Fixes: 787cfbd9a9 ("ui: remove screen and viewports")
Changelog-fixed: The address-book completion popovers now again appear
 under the field being completed.
Signed-off-by: Karel Balej <balejk@matfyz.cz>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2025-01-18 11:17:20 +01:00
Robin Jarry
6b97085ae5 tab: fix broken history on removal
Given the following tab layout: name(index). The current index is 2 and
history is considered empty:

    MessageList       TermFoo      [TermBar]       Viewer
    0                 1             2              3

If we focus TermFoo, index 2 is added to history and current index
becomes 1:

    MessageList      [TermFoo]      TermBar        Viewer
    0                 1             2              3

Now, if we close TermFoo, the last item in the history (2) is popped and
selected:

    MessageList      TermBar      [Viewer]
    0                1             2

This leads to selecting the message viewer whereas TermBar should have
been selected.

A different issue happens when the tab history index is out of bounds.
For example:

    MessageList       TermFoo      [TermBar]
    0                 1             2

Move to TermFoo, 2 is pushed to history:

    MessageList      [TermFoo]      TermBar
    0                 1             2

Close TermFoo, last index in history (2) is invalid, current index
remains selected but not completely:

    MessageList      [TermBar]
    0                 1

The widget/terminal in TermBar will not be focused or made visible to
the ui (via (Visible).Show(true)) until one key is pressed. Effectively
delaying interaction with the program running in it.

Replace a list of index with a list of pointers to *Tab objects for the
history. This makes it impervious to removal, reordering and removes
the need to recompute the history indexes.

Limit the history to 256 items to avoid memory hog after a long time.

When removing the current tab, ensure "something" is selected. If the
history is empty, select the next best thing.

Suggested-by: Koni Marti <koni.marti@gmail.com>
Reported-by: Brandon Sprague <brandon@sprague.mx>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
2025-01-10 17:07:33 +01:00
Tim Culverhouse
5b57d24afd textinput: make completions run async with cancellation
Make the Completer interface accept a context.Context. Provide a
cancellation feature on text input tab completion to cancel an inflight
completion command. This is particularly useful for address book
completion if the user has specified a network-accessing command, eg
carddav-query. The command is started according to the completion delay,
but is cancellable if another request comes in. We also check for
cancellation after the request is complete to ensure we only show valid
completion results.

Changelog-changed: Tab completions for text fields are run
 asynchronously. In-flight requests are cancelled when new input
 arrives.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-10-24 22:13:51 +02:00
Robin Jarry
3c9ad93801 completion: display descriptions next to choices
Use go-opt v2 new completion API which returns items descriptions along
with their text values.

Display the descriptions after the items separated by two spaces. Wrap
the descriptions in parentheses to better indicate that they are not
part of the completion choices. Limit the description length to 80
characters to avoid display issues.

Add a new style object completion_description in stylesets. By default,
the object will be rendered with a dimmed terminal attribute. Update all
stylesets and documentation accordingly.

Implements: https://todo.sr.ht/~rjarry/aerc/271
Link: https://git.sr.ht/~rjarry/go-opt/commit/ebeb82538395a
Changelog-added: Command completion now displays descriptions next
 to completion items.
Changelog-added: New `completion_description` style object in style
 sets used for rendering completion item descriptions.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bojan Gabric <bojan@bojangabric.com>
Tested-by: Jason Cox <me@jasoncarloscox.com>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
2024-10-23 10:22:51 +02:00
Koni Marti
163ea3ec7d aerc: support terminal-based pinentry programs
Support terminal-based pinentry programs. Suspend vaxis before running
the command that can trigger a pinentry call. Provide the proper tty in
the GPG_TTY environment variable (and set a TERM variable if not
provided; this is necessary for pinentry-curses). Finally, resume vaxis.

To enable terminal-based pinentry support, you have to set

	[general]
	use-terminal-pinentry = true

in your aerc.conf. Any GUI-based pinentry programs will work the same as
before if this option is not set to true.

To test pinentry-tty, add the following to your ~/.gnupg/gpg-agent.conf:

	pinentry-program /usr/bin/pinentry-tty

and kill all running gpg-agents:

	$ killall gpg-agent

Fixes: https://todo.sr.ht/~rjarry/aerc/202
Changelog-fixed: Terminal-based pinentry programs
 (e.g. `pinentry-curses`) now work properly.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-10-12 00:12:25 +02:00
Koni Marti
899d16f20f tabs: update ui config in any tab
Update UI config in tabs.

Signed-off-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Inwit <inwit@sindominio.net>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-08-20 12:26:47 +02:00
Aron Lebani
fff69046b0 view-message: add option to view message in background tab
Add a -b flag to the :view command to open messages in a background tab
instead of automatically switching to the new tab after opening. This is
similar to opening browser tabs in the background. More generally, adds
a new function app.NewBackgroundTab so that it is possible to enable other
tabs to be opened in the background in the future.

Implements: https://todo.sr.ht/~rjarry/aerc/266
Changelog-added: Add `-b` flag to the `:view` command to open messages
 in a background tab.
Signed-off-by: Aron Lebani <aron@lebani.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-08-04 18:26:58 +02:00
Tim Culverhouse
f8b74a9a9f ui: add :redraw command
Add a :redraw command to force a repaint of the entire screen.

Changelog-added: New `:redraw` command to force a repaint of the
 screen.
Requested-by: Remko Tronçon <r@mko.re>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-08-03 17:39:57 +02:00
Tim Culverhouse
894c97e374 ui: make textinput grapheme aware
The textinput widget operated on a slice of runes, and naively assumed
a rune was a "character". When deleting or navigating the cursor through
text which contains multi-codepoint characters (such as emoji), the
cursor index could desync and cause panics.

Use a slice of vaxis.Characters instead of runes to more accurately
reflect the index state of the cursor with respect to characters.

Fixes: https://todo.sr.ht/~rjarry/aerc/263
Reported-by: Bence Ferdinandy <bence@ferdinandy.com>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
Reviewed-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-07-02 22:12:45 +02:00
Robin Jarry
535e7fe3aa vaxis: fix panic trace print on stderr
By default, vaxis tries to open stderr, stdout and stdin in that order
and uses the first one as its TTY file descriptor.

Upon exit, vaxis.Close() closes that file descriptor. When aerc panics,
our panic handler calls UICleanup() which is an alias for vaxis.Close().
This effectively makes os.Stderr unusable and all error messages are
written to a closed file descriptor. This also break the regular go
runtime panic() handler which prints on stderr as well.

Use an explicit /dev/tty path instead of stderr to keep it open.

Fixes: 6eff242090 ("ui: so long tcell")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
2024-04-13 21:47:50 +02:00
Tim Culverhouse
83c3a4051b ui: update vaxis and only use disambiguate csi-u flag
Update vaxis to 0.8.2, which adds the ability to specify any CSI-u flag
combination. Explicitly only use the disambiguate flag. This enables
aerc to have additional keybinds not previously possible (C-i, C-m)
while preventing some internal logic bugs relating to single-modifier
key presses. While these events can be useful, they are not needed in
aerc and aerc currently would need several workarounds to properly
handle them so let's just not request them in the first place.

Fixes a bug with encoding shift+space in the presence of CSI-u in the
terminal widget

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Inwit <inwit@sindominio.net>
Tested-by: Jason Cox <dev@jasoncarloscox.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-26 09:22:40 +01:00
Tim Culverhouse
3c01fd0fcd ui: enable CSIu key encoding
Enable CSIu key encoding protocol when support is detected. This will
enable keybinds which traditionally have been unavailable due to
conflicting with other keys (C-i, C-m, C-[, etc).

Remove numlock and capslock from all keypresses to prevent interfering
with key matching.

Changelog-added: Virtually any key binding can now be configured in
 `binds.conf`, including Shift+Alt+Control modifier combinations.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-22 21:46:15 +01:00
Robin Jarry
782a17dfb0 revert: "ui: enable kitty keyboard protocol"
This reverts commit d73cf33c2c.

This breaks virtually all key bindings on foot. Almost zero ctrl-
bindings work, and even in some cases, single key binds, like n don't
register anymore.

It looked harmless, but I should probably have tested before applying
this.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
2024-02-19 22:29:52 +01:00
Tim Culverhouse
d73cf33c2c ui: enable kitty keyboard protocol
Enable kitty keyboard protocol when support is detected. This will
enable keybinds which traditionally have been unavailable due to
conflicting with other keys (C-i, C-m, C-[, etc).

Reported-by: Jonathan Dowland <jon+aerc-discuss@dow.land>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Jonathan Dowland <jon@dow.land>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-19 21:06:22 +01:00
Robin Jarry
8edf7b0e4d log: move package to lib
This has nothing to do at the root of the source tree.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Bence Ferdinandy <bence@ferdinandy.com>
2024-02-14 23:04:38 +01:00
Tim Culverhouse
6314e2dc67 vaxis: update to v0.7.2 and update ansi parser
Update Vaxis to v0.7.2 to gain performance improvements and StyledString
parsing. The Vaxis parser fully accounts for the terminal's capability
to display wide characters.

Use the Vaxis StyledString parser to parse and style ansi-encoded
strings. Remove unneeded code and tests.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:49:14 +01:00
Tim Culverhouse
2236e8bbeb aerc: set title using vaxis
Set the window title using Vaxis at UI initialization.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:49:01 +01:00
Tim Culverhouse
58f94fa0a1 mouse: use vaxis mouse events
Replace all tcell.EventMouse events with vaxis mouse events

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:56 +01:00
Tim Culverhouse
345962e33c terminal: replace tcell-term with vaxis terminal
Replace tcell terminal with the vaxis terminal. The vaxis terminal is a
port of tcell term.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:51 +01:00
Tim Culverhouse
a60f2c19a0 style: use vaxis style everywhere
Replace all tcell.Style objects with vaxis.Style objects

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:50 +01:00
Tim Culverhouse
cdc90afbaa aerc: replace tcell keys with vaxis keys
Replace all instances of tcell key usage with vaxis keys

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:48 +01:00
Tim Culverhouse
f001f65240 fill: replace tcell.Style with vaxis.Style
Replace the Fill implementation with vaxis style objects

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:47 +01:00
Tim Culverhouse
0fd5f41157 ui: initialize vaxis directly, drop tcell.Screen initialization
Use Vaxis library directly to initialize the UI, dropping the need for a
tcell Screen implementation

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:46 +01:00
Tim Culverhouse
787cfbd9a9 ui: remove screen and viewports
Remove references to tcell.Screen or views.Viewports. Convert Contexts
and the core UI struct to use Vaxis objects only.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:44 +01:00
Tim Culverhouse
63b9706441 aerc: change event interfaces to vaxis events
Modify the function signature of Event and MouseEvent interfaces to
accept vaxis events. Note that because a vaxis event is an empty
interface, the implementations are not affected and the events are
delivered as they were before

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:48:42 +01:00
Tim Culverhouse
4e26faf498 msgviewer: implement inline image viewing
Implement inline image viewing for jpeg, png, bmp, tiff, and webp
formats. When a user has no configured image filter and the image is
supported and the terminal has either sixel or kitty image protocol
support, the image will be displayed in the message viewer.

Always clear the screen before each draw. This call is necessary in
vaxis to allow for images to be cleared properly between renders. There
is no performance impact: the call only resets each cell to a blank
cell, and aerc will redraw each one already.

Changelog-added: Inline image previews when no filter is defined for
 `image/*` and the terminal supports it.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:47:29 +01:00
Tim Culverhouse
0ef4717b2a ui: create and expose vaxis Window with Context
Create and expose a vaxis.Window object with each Context. vaxis.Windows
are used for creating local coordinates (similar to the views.View API
that tcell provides).

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:47:18 +01:00
Tim Culverhouse
6eff242090 ui: so long tcell
Replace tcell with vaxis. Vaxis provides several new features (none of
which are included in this commit). All behavior should be exactly the
same as previous, with one exception:

   Vaxis does not have an internal terminfo library. Some terminals will
   now have RGB that didn't before, as well as any other feature that
   was falling back to some unknown state.

Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-02-12 13:46:27 +01:00
delitako
936d519a67 tabs: optimize switching by offsets
I imagine no sane user requires aerc to correctly handle commands like
`:next-tab 1000000000`, but I tried anyway and it froze aerc while
also eating up many GBs of system memory. This behavior is not ideal,
so I improved it.

This commit adds functions for selecting a tab at an offset from the
currently-selected tab and changes the next-tab, prev-tab, and
change-tab commands to use these functions instead of looping.

Signed-off-by: delitako <delitako@delitako.xyz>
Tested-by: Thomas Böhler <witcher@wiredspace.de>
Reviewed-by: Thomas Böhler <witcher@wiredspace.de>
Acked-by: Robin Jarry <robin@jarry.cc>
2024-01-26 20:27:08 +01:00
Robin Jarry
5b76547c3b commands: add menu
Add a new :menu command that can be used to spawn a shell command in an
interactive dialog and execute aerc commands for each of the lines
printed on its standard output like xargs(1) would do in a shell.

The shell command can be configured in aerc.conf under
[general].default-menu-cmd and overridden via the :menu -c <cmd> option.

There are two flags to provide input text to the shell command which can
be useful in combination with other aerc commands:

	-a: All account names, one per line:
		'<account>' LF

	-d: All current account directory names, one per line:
		'<directory>' LF

	-ad: All directories of all accounts, one per line:
		'<account>' '<directory>' LF

Here are some examples:

	:menu -adc fzf :cf -a
	:menu -c 'fzf --multi' :attach
	:menu -dc 'fzf --multi' :cp

And also for key bindings:

	<C-p> = :menu -adc fzf :cf -a<Enter>

Changelog-added: New `:menu` command to invoke other aerc commands
 based on a shell command output.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
Tested-by: Johannes Thyssen Tishman <johannes@thyssentishman.com>
2024-01-20 21:56:52 +01:00
Robin Jarry
b3dc63d69c complete: only display popover for more than one choice
When there is only one completion choice available, accept the
completion immediately upon a <Tab> key press. This is consistent with
how most completion engines work (bash, vim, etc.).

Reported-by: Johannes Thyssen Tishman <johannes@thyssentishman.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Johannes Thyssen Tishman <johannes@thyssentishman.com>
2023-11-22 23:35:22 +01:00
Robin Jarry
485a2c52f6 completion: hide quotes from choices
When completion choices are surrounded by quotes to make sure that they
will be interpreted as a single argument, hide them before presenting
the choices to the user. It makes the UI cluttered and harder to read.

The completion values remain identical, the quotes will be inserted when
the user accepts one choice.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Inwit <inwit@sindominio.net>
2023-11-12 12:53:11 +01:00
Robin Jarry
0b0095eead complete: allow disabling automatic completion
Allow setting complete-min-chars = manual to disable automatic
completion.

Changelog-added: Setting `complete-min-chars=manual` in `aerc.conf` now
 disables automatic completion, leaving only manually triggered
 completion.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
2023-11-02 16:30:57 +01:00
Robin Jarry
44a55d41ad complete: allow setting the completion key binding
Until now, if less than complete-min-chars were entered or if
completion-delay had not expired yet, the only way to force trigger
completion was to press <tab>.

In some cases, <tab> is already bound to another action (for example
:next-field in the compose::editor context). This makes forcing the
completion impossible.

Allow defining a key to trigger manual completion via the new $complete
special entry in binds.conf.

Leave the default binding to <tab>. Set it to <C-o> in the
[compose::editor] to avoid conflicting with the existing <tab> binding.

Changelog-added: Customize key to trigger completion with `$complete` in
 `binds.conf`.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
2023-11-02 16:30:47 +01:00
Nojus Gudinavičius
4ceafd0b7b commands: add :suspend
Add :suspend to suspend the aerc process, returning to shell. Include
documentation and default Ctrl-z keybinding for it.

Changelog-added: New `:suspend` command bound to `<C-z>` by default.
Signed-off-by: Nojus Gudinavičius <nojus.gudinavicius@gmail.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
2023-10-24 22:55:40 +02:00
Robin Jarry
1300b2c81b ui: export global functions
There is no need for an UI object. The Aerc.ui field is unused. And
there is a single instance of it anyway.

Move the object's public fields as global variables and change methods
to public functions.

This makes the code cleaner and removes boilerplate.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Moritz Poldrack <moritz@poldrack.dev>
2023-10-11 10:21:56 +02:00
Bence Ferdinandy
2fbce2e2c9 mouse: fix offset in tab title clickable area
Since templates have been introduced into the tab titles the clickable
area has been offset from the actual title. This is because the
clickable areas are calculated based on the tab names, which can now be
different from the acually shown titles. Extract the logic of getting
the display name of a tab from TabStrip and add as method of Tab. Also
extract the magic constant 32. Use the method and const in both clicked
and Draw. Switch from using len() to runewidth, when calculating the
length of the display name.

Fixes: https://todo.sr.ht/~rjarry/aerc/162
Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Reviewed-by: Koni Marti <koni.marti@gmail.com>
2023-08-03 22:28:07 +02:00
Koni Marti
6713a8f458 wizard: display warning when focus is lost
Display the warning that the password is stored in plaintext after the
focus of the password input field is lost.

The current behavior of showing the warning after the first character is
entered is ackward and confusing.

It also eliminates the need to debounce the warning when a password is
pasted.

Reported-by: Brad <super1337@posteo.net>
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
2023-08-03 22:25:42 +02:00
Oskar Sharipov
cb57cd20e9 textinput: fix deleteWord with an only whitespace
Fix a panic in the textinput.deleteWord when text is a whitespace
symbol.

Add tests for textinput.

Fixes: https://todo.sr.ht/~rjarry/aerc/183
Signed-off-by: Oskar Sharipov <oskargit@riseup.net>
Acked-by: Robin Jarry <robin@jarry.cc>
2023-07-28 21:18:09 +02:00
Koni Marti
0fc5ffb260 textinput: fix stemming with multi-byte chars
Fix a panic in the textinput when using multi-byte chars in the
completions.

Fixes: https://todo.sr.ht/~rjarry/aerc/180
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
2023-06-22 10:39:19 +02:00
Robin Jarry
916bca33ea ui: fix deadlocks in message channel
There are several ways the ui message channel can fill up leading to
deadlocks.

1) Invalidate() changes the value of uiState to DIRTY. The following
   call sequence:

      QueueRedraw()
      Invalidate()
      QueueRedraw()

   Leads to multiple nil messages being queued in the message channel
   whereas one could assume that the second QueueRedraw() would do
   nothing. This is caused by the tri-state nature of uiState.

2) We use the same channel to convey state change, keyboard events and
   redraw requests. Since a keyboard event almost always triggers
   a redraw, we end up trying to append a redraw message in the same
   goroutine that reads from the channel. This triggers a deadlock when
   there are more than 50 pending messages.

Solve the issue by using multiple channels, one per type of message that
needs to be sent to the main ui thread.

Remove QueueRedraw() and merge its functionality in Invalidate(). Only
use a DIRTY/CLEAN state to determine if something needs to be queued in
the redraw channel.

Use a channel for quitting instead of an atomic. Restructure some code
functions to have a cleaner API.

Use a for loop in the main thread and select from all channels.

Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Maarten van Gompel <proycon@anaproy.nl>
2023-05-20 22:09:43 +02:00