aboutsummaryrefslogtreecommitdiffstats
path: root/commands
Commit message (Collapse)AuthorAgeFilesLines
* statusline: add column based render formatRobin Jarry2023-02-201-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the spirit of commit 535300cfdbfc ("config: add columns based index format"), reuse the column definitions and table widget. Add automatic translation of render-format to column definitions. Allow empty columns to be compatible with the %m (mute) flag. Rename the State object to AccountState to be more precise. Reuse that object in state.TempateData to expose account state info. Move actual status line rendering in StatusLine.Draw(). Add new template fields for status specific data: {{.ConnectionInfo}} Connection state. {{.ContentInfo}} General status information (e.g. filter, search) {{.StatusInfo}} Combination of {{.ConnectionInfo}} and {{.StatusInfo}} {{.TrayInfo}} General on/off information (e.g. passthrough, threading, sorting) {{.PendingKeys}} Currently pressed key sequence that does not match any key binding and/or is incomplete. Display a warning on startup if render-format has been converted to status-columns. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* statusline: move files to lib/stateRobin Jarry2023-02-207-20/+20
| | | | | | | | These modules will not handle statusline rendering after next commit. Move them in lib/state to make next commit easier to review. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* triggers: use templates instead of % mini languageRobin Jarry2023-02-201-5/+16
| | | | | | | | | | | | | | | | | | | | | Since previous commit, all commands now support expanding text/template markup. Reuse that for the new-email trigger command. Update commands.ExecuteCommand to take optional *AccountConfig and *MessageInfo arguments. If these are nil, fallback to using the currently selected account and message (if any). Pass the proper *AccountConfig and *MessageInfo objects when firing the trigger command so that these are used instead of the currently selected ones. If new-email contains % placeholders, try to convert them to template markup reusing the same conversion added in commit 535300cfdbfc ("config: add columns based index format"). Warn the user that they need to update their configuration file. Signed-off-by: Robin Jarry <robin@jarry.cc> Reviewed-by: Moritz Poldrack <moritz@poldrack.dev>
* commands: expand template placeholdersAivars Vaivods2023-02-201-1/+45
| | | | | | | | | Interpret go template constructs in all aerc command arguments based on the currently selected account, folder and message (if any). Signed-off-by: Aivars Vaivods <aivars@vaivods.lv> Signed-off-by: Robin Jarry <robin@jarry.cc> Reviewed-by: Tim Culverhouse <tim@timculverhouse.com>
* log: add debug for send configurationBence Ferdinandy2023-02-121-0/+8
| | | | | | | | Make it easier to debug send configurations. References: https://todo.sr.ht/~rjarry/aerc/127 Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* tabs: use template for compose tabsTim Culverhouse2023-02-127-66/+7
| | | | | | | | | | | | | | | | | | | | | | | | Use a template for compose tabs. Other available values: Account string Subject string To []*mail.Address From []*mail.Address Cc []*mail.Address Bcc []*mail.Address OriginalFrom []*mail.Address When you use To, From, CC, BCC, or OriginalFrom the title will only be updated when an editing field has lost focus. This is so we don't end up calling "PrepareHeader" on every keystroke, which will likely error out anyways since it will be an invalid header. Subject still updates every keystroke. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* config: add option for SMTP HELO/EHLO local domainKarel D. Kopecký2023-02-021-2/+14
| | | | | | | | | | | | | | | | Expose go-smtp functionality for setting the domain name as a config option. This allows aerc to communicate with SMTP servers with strict antispam measures without relying on sendmail. In theory, this should be set to a fully qualified domain name, but some servers simply forbid the use of "localhost", so it is reasonable to let the user set whatever value works for them. For comparison, this is equivalent to the functionality of the "domain" option of msmtp. Signed-off-by: Karel D. Kopecký <kdk@freeshell.de> Acked-by: Robin Jarry <robin@jarry.cc>
* switch-account: also switch account configurationBence Ferdinandy2023-01-261-0/+1
| | | | | | | | | When switching accounts, headers were updated, but not the account configurations in the composer. Switch the account config also and add a debug log to send with the uri being used. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* logging: add trace to every command callBence Ferdinandy2023-01-261-0/+2
| | | | | | | | | A previous commit introduced a trace loglevel, but aerc doesn't make much use of it. Logging is not very informative either. Add a log.Tracef to every command and log the provided arguments as well. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* lint: add missing panic handlers in goroutinesRobin Jarry2023-01-066-0/+8
| | | | | | | | These issues were all reported by the new custom analyzer introduced in previous commit. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* doc: fix English typosRobin Jarry2023-01-061-1/+1
| | | | | | | Reported by Lintian (Debian). Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* templates: change fields as lazy functionsRobin Jarry2023-01-047-10/+8
| | | | | | | | | No need to pre-render fields that are not necessarily accessed in templates. Change fields to functions that are evaluated only when required. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* config: parse account from and aliases onceRobin Jarry2023-01-043-36/+7
| | | | | | | | | Instead of accepting any garbage for these configuration fields, parse them when parsing accounts.conf and store mail.Address objects. Reuse these objects everywhere. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* model: change flags array to bitmaskRobin Jarry2023-01-044-12/+5
| | | | | | | Using a list of integers is not optimal. Use a bit mask instead. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* send: add option to send&archiveBence Ferdinandy2023-01-043-12/+36
| | | | | | | | | Add `:send -a flat|month|year` to send, which archives the message being replied to. Extract most of archive logic into a separate function to make sure it behaves as manual archiving. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* split: refactor to prevent stuck splitsTim Culverhouse2022-12-251-6/+7
| | | | | | | | | | Refactor split logic (again...) to prevent stuck splits. Use callback from msgstore.Select to tell the split which message to display. This keeps the account from having to track displayed messages, which prevents race conditions in certain situations. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* smtp: remove requirement for oauthbearer token-endpointTim Culverhouse2022-12-211-7/+6
| | | | | | | | | | | | | | | The SMTP configuration is slightly different between oauthbearer and xoauth2. The oauthbearer requires a token-endpoint, while xoauth2 does not. The IMAP version of oauthbearer also does not require a token-endpoint. If one is specified, the token is treated as a refresh token. Modify the SMTP usage to work the same way: a token is an access token unless a token-endpoint is specified Reported-by: Cameron Samak <csamak@apache.org> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* attach: don't glob hidden filesMoritz Poldrack2022-12-202-0/+26
| | | | | | | | | | | | Most of the time it is not wanted to attach hidden files, but by default globbing does include hidden files. Add a small check that removes hidden files from the results if they are not explicitly globbed for or inside a hidden directory. Implements: https://todo.sr.ht/~rjarry/aerc/83 Signed-off-by: Moritz Poldrack <git@moritz.sh> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* split: use a sensible default widthMoritz Poldrack2022-12-191-0/+8
| | | | | | | | | | | | | Guessing a width/height with v?split is rather bothersome, using a sensible value based on the user's terminal would be preferable. This also prevents confusion when running :v?split without a number seemingly does not open a split. Initialize width as half the width of the message list and height as an eight of the message list. Signed-off-by: Moritz Poldrack <git@moritz.sh> Acked-by: Robin Jarry <robin@jarry.cc>
* reply: refactor close-on-reply setting to -c flagBence Ferdinandy2022-12-151-7/+10
| | | | | | | | Previously close-on-reply was implemented as a setting, making it unflexible. Refactor so it is a flag to reply `:reply -c`. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Robin Jarry <robin@jarry.cc>
* findNextNonDeleted: set next to nil if last messageTim Culverhouse2022-12-141-0/+3
| | | | | | | | | | | The introduction of the iterator means the "next" non-deleted message is never nil, it will always be equal to the previous message (meaning there is only one message left and it is the one we are deleting). In this case, deliberately set next to nil so that the remove tab on delete logic works properly. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* split: refactor split update logicTim Culverhouse2022-12-141-3/+0
| | | | | | | | | | | | | | | | | | | | | | Refactor split update logic to more simply update the split. Through the evolution of the split logic, additional variables were stored within the account which allows for cleaner updating of the split. Compare selected UID instead of pointer to message when deciding not to update split. Allow splits to be created and closed when no message is selected. The split will be filled with a ui.Fill (blank). The user will only see a border at the split location when no message is selected. Rename clearSplit to closeSplit, as it is only used in the case when the user doesn't want a split anymore. Ensure that the selected UID is reset to the magic UID when there are no messages left in the message store. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* config: make various sections accessible via global varsRobin Jarry2022-12-1418-33/+38
| | | | | | | | | | | | | | | | | | | | There is only one instance of AercConfig which is associated to the Aerc widget. Everywhere we need to access configuration options, we need somehow to get a reference either to the Aerc widget or to a pointer to the AercConfig instance. This makes the code cluttered. Remove the AercConfig structure and every place where it is referenced. Instead, declare global variables for every configuration section and access them directly from the `config` module. Since bindings and ui sections can be "contextual" (i.e. per account, per folder or per subject), leave most local references intact. Replacing them with config.{Ui,Binds}.For{Account,Folder,Subject} would make this patch even more unreadable. This is something that may be addressed in the future. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* compose: allow writing multipart/alternative messagesRobin Jarry2022-12-071-0/+73
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Add a new :multipart command that can be executed on the composer review screen. This command takes a MIME type as argument which needs to match a setting in the new [multipart-converters] section of aerc.conf. A part can be removed by using the -d flag. The [multipart-converters] section has MIME types associated with commands. These commands are executed with sh -c every time the main email body is updated to generate each part content. The commands are expected to output valid UTF-8 text. If a command fails, an explicit error will be printed next to the part MIME type to allow users to debug their issue but the email may still be sent anyway with an empty alternative part. This is mostly intended for people who *really* need to send html messages for their boss or for corporate reasons. For now, it is a manual and explicit action to convert a message in such a way. Here is an example configuration: [multipart-converters] text/html = pandoc -f markdown -t html And the associated binding to append an HTML alternative to a message: [compose::review] H = :multipart text/html<enter> hh = :multipart -d text/html<enter> Link: https://lists.sr.ht/~rjarry/aerc-discuss/%3CCO5KH4W57XNB.2PZLR1CNFK22H%40mashenka%3E Co-authored-by: Eric McConville <emcconville@emcconville.com> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* view: add close-on-reply optionBence Ferdinandy2022-12-021-1/+11
| | | | | | | | | | | Opening an email to view and then to reply will have two tabs open, and after a reply the view tab needs to be closed manually. Allow the user to set a close-on-reply option that will close the viewer tab when replying and reopen the viewer tab in case the reply is not sent. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Tested-by: Inwit <inwit@sindominio.net> Signed-off-by: Robin Jarry <robin@jarry.cc>
* logging: rename package to logRobin Jarry2022-12-0220-82/+81
| | | | | | | | | | Use the same name than the builtin "log" package. That way, we do not risk logging in the wrong place. Suggested-by: Tim Culverhouse <tim@timculverhouse.com> Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* logging: homogenize levelsRobin Jarry2022-12-028-18/+15
| | | | | | | | | | | | | | | | | | The main goal is to ensure that by default, the log file (if configured) does not grow out of proportions. Most of the logging messages in aerc are actually for debugging and/or trace purposes. Define clear rules for logging levels. Enforce these rules everywhere. After this patch, here is what the log file looks like after starting up with a single account: INFO 2022/11/24 20:26:16.147164 aerc.go:176: Starting up version 0.13.0-100-g683981479c60 (go1.18.7 amd64 linux) INFO 2022/11/24 20:26:17.546448 account.go:254: [work] connected. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* doc: extract accounts and binds into separate man pagesRobin Jarry2022-11-241-0/+2
| | | | | | | | | | | | | aerc-config(5) is getting too big and cluttered. Only keep aerc.conf settings in it. Move binds.conf settings in aerc-binds(5) and accounts.conf settings in aerc-accounts(5). Adjust all references accordingly. Update the README to reference the two new man pages. Update the Makefile to install them in proper locations. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Koni Marti <koni.marti@gmail.com>
* ui: box and frame an interactive widgetKoni Marti2022-11-211-1/+2
| | | | | | | | Draw a framed box with a title containing an interactive-drawable widget. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* attach: open file picker menu with -m flagKoni Marti2022-11-211-2/+91
| | | | | | | | | | | | | | | | | | | | | Open a user-defined file picker with the -m flag for the attach command to select attachments. Specify your file picker of choice with the 'file-picker-cmd' in the [composer] section of aerc.conf, e.g. "file-picker-cmd=fzf -m". A '%s' placeholder can be used in the 'file-picker-cmd' which is then substituted for the argument <arg> provided to :attach -m <arg>. For example, when you set 'file-picker-cmd=find %s -type f | fzf -m', you can easily change the directory to start the search with ':attach -m <path-to-search>'. Tested with fzf, fzy and peco. Implements: https://todo.sr.ht/~rjarry/aerc/108 Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* commands: remove broken :set commandRobin Jarry2022-11-161-70/+0
| | | | | | | | | This may have worked at some point in time but that is not the case anymore. To accommodate for the rework of the config module, it needs to be removed anyway. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* move and archive: common code for common operationBence Ferdinandy2022-11-132-43/+57
| | | | | | | | | | | | The code of Archive and Move are slightly different, even though they essentially do the same thing sans the destination and archive always creating the destination if it doesn't exist. Extract common code into a function used by both. This will also result in Move now also respecting next-message-on-delete. Signed-off-by: Bence Ferdinandy <bence@ferdinandy.com> Acked-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* reply: allow to override localized Re regexp in configurationjp392022-11-132-6/+3
| | | | | | | | | | | | | | | My corporate email server annoyingly adds an "[External] " prefix when delivering emails from outside my organization. I'd like to be able to automatically strip it from the subject line when replying to external emails. With this patch, I can achieve it by setting this line in my account configuration: subject-re-pattern = ^(\[External\] : )?((?i)((AW|RE|SV|VS|ODP|R): ?)+) Signed-off-by: jp39 <jp39@gmx.com> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* composer: add message previewKoni Marti2022-11-091-1/+12
| | | | | | | | | | Add message preview to the composer. Add preview option to the review window. Open the message in a message viewer before sending to check the headers and attachments. Implements: https://todo.sr.ht/~rjarry/aerc/86 Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* lib: prepare attachments for multiple readsKoni Marti2022-11-092-2/+10
| | | | | | | | | | | Prepare attachments for multiple reads. The data for lib.PartAttachment is stored as an io.Reader which can only be read once. This will cause an issue when we want to call composer.WriteMessage multiple times, i.e. for a message preview. We fix this by keeping a copy of the data and create a new reader everytime the attachment is read. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* viewer: open rfc822 attachmentsKoni Marti2022-11-091-9/+19
| | | | | | | | | | Open message/rfc822 attachments from the message viewer when no filter is defined for this mimetype. When the rfc822 part is selected, call the eml command to open the attachment in a new message viewer. Suggested-by: Jens Grassel <jens@wegtam.com> Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* commands/eml: open and view eml filesKoni Marti2022-11-091-0/+63
| | | | | | | | | Open and view eml data from a file. Call the eml command and use the completion feature to select an eml file from disk. The eml data will be opened in the message viewer. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* lib: implement an eml message viewKoni Marti2022-11-092-1/+19
| | | | | | | | | Implement a MessageView representation for eml data that are not stored in a message store. With this, we can display any rfc822 message data in the message viewer. Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* envelope: display message envelope infoKoni Marti2022-10-261-0/+152
| | | | | | | | | Display entire message envelope in a user-friendly dialog popup with the :envelope command. All header fields can be displayed with the -h flag. Fixes: https://todo.sr.ht/~rjarry/aerc/85 Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* pipe: reorder patches based on email subjectsRobin Jarry2022-10-251-25/+7
| | | | | | | | | | | | | | | | | | | | | The Message-Id header cannot be relied upon as users can tweak it before sending. The subject seems a more reliable basis to reorder patches. Change the logic of sorting. Previously, all messages were required to look like patches to be sorted. Now if at least one message looks like a patch, all messages will be sorted by Subject before piping them. Since `git am` ignores non-patch messages, it should allow piping series of emails including reviews and comments without getting confusing errors. I have tested that this works on multiple series that appeared out of order in my INBOX with the following command (after marking the messages): :pipe -m sed -n 's/^Subject: //p' Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
* split: clamp minimum split size to 1Tim Culverhouse2022-10-201-0/+4
| | | | | | | | | | | | The split command allows delta size changes, which triggers a condition where the split can overflow into the dirlist. Clamp the minimum size of a split or vsplit to "1" to prevent the view from overflowing, or completely covering the message list. A split of 0 will still clear the split. Reported-by: Koni Marti <koni.marti@gmail.com> Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* split: prevent panic when store is not setTim Culverhouse2022-10-191-0/+3
| | | | | | | | | | | | Prevent panic when split is called but the msgstore is either not initialized or has no UIDs. This condition could be triggered by calling :split or :vsplit immediately at startup. Use the same logic as the :view command, which could operate in a similar manner. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* msgview: enable next/prev with unfetched headersKoni Marti2022-10-191-14/+26
| | | | | | | | | | | Fix message view behavior for unfetched headers. When scrolling "over" the message list boundary, current behavior is to close the message viewer tab. Now, the headers will be fetched so that we can scroll through the messages uninterrupted. Fixes: https://todo.sr.ht/~rjarry/aerc/90 Signed-off-by: Koni Marti <koni.marti@gmail.com> Acked-by: Robin Jarry <robin@jarry.cc>
* split: prevent opening split when no messages are selectedTim Culverhouse2022-10-191-4/+2
| | | | | | | | | The [v]split command panics when it is run with no message selected, or when messages aren't loaded. Check for a valid selected message before creating a split, and report an error if one isn't selected. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* command/help: remove helpClose functionTim Culverhouse2022-10-191-7/+0
| | | | | | | | | | | | | The helpClose function is used to call UpdateScreen on MessageViewer, which has the effect of invalidating and redrawing the message view. This logic is redundant with the addition of tcell-term and the main event loop. Remove the helpClose calls. Remove the UpdateScreen methods from messageviewer: those functions are only used by the helpClose function. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Koni Marti <koni.marti@gmail.com>
* ui: add :split and :vsplit view optionsTim Culverhouse2022-10-181-0/+63
| | | | | | | | | | | Add :split and :vsplit commands, which split the message list view to include a message viewer. Each command takes an int, or a delta value ("+1", "-1"). The int value is the resulting size of the message list, and a new message viewer will be displayed below / to the right of the message list. This viewer *does not* set seen flags. Signed-off-by: Tim Culverhouse <tim@timculverhouse.com> Acked-by: Robin Jarry <robin@jarry.cc>
* compose: warn before sending without attachmentJason Cox2022-10-171-2/+37
| | | | | | | | | | Prevent the embarrassing forgotten attachment scenario by warning the user before sending a message that may need an attachment but does not have one. Whether a message needs an attachment is determined by testing a configurable regex against the message body. Signed-off-by: Jason Cox <dev@jasoncarloscox.com> Acked-by: Robin Jarry <robin@jarry.cc>
* notmuch: add "tag" alias for modify-labels commandinwit2022-10-171-1/+1
| | | | | | | | In order to make things easier for newcomers from notmuch, add a tag command which is just an alias for modify-labels. Signed-off-by: inwit <inwit@sindominio.net> Acked-by: Tim Culverhouse <tim@timculverhouse.com>
* commands: split open-link in separate fileRobin Jarry2022-10-162-19/+46
| | | | | | | | | These two commands have virtually zero in common. Move open-link in its own file. Signed-off-by: Robin Jarry <robin@jarry.cc> Tested-by: Inwit <inwit@sindominio.net> Acked-by: Moritz Poldrack <moritz@poldrack.dev>
* msgpart: factorize mime type and filename constructionRobin Jarry2022-10-165-11/+5
| | | | | | | Reduce code duplication. Signed-off-by: Robin Jarry <robin@jarry.cc> Acked-by: Moritz Poldrack <moritz@poldrack.dev>