| Commit message (Collapse) | Author | Age | Files | Lines |
|
|
|
|
|
|
|
|
| |
Similar to switch and .StyleSwitch, add map and .StyleMap to work on
lists. An extra "exclude" item is available to filter elements out of
the list.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Inwit <inwit@sindominio.net>
|
|
|
|
|
|
|
|
|
| |
Don't set the Seen flag when an error occurs during opening the message.
Fixes: https://todo.sr.ht/~rjarry/aerc/125
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Tested-by: Moritz Poldrack <moritz@poldrack.dev>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
List the folders in arrival order when dirstore.List() is called instead
of returning it in an arbitrary order.
If enable-folders-sort=false and dirlist-tree=false, the directory list
will arbitrarly reshuffle when changing directories because the
dirlist.dirs are generated from keys in a map in the dirstore.
Fixes: https://todo.sr.ht/~rjarry/aerc/178
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Allow accessing email flags via boolean properties instead of having to
rely on obscure regular expressions on (.Flags | join ""). With this
patch, it is now possible to do this:
[ui]
index-columns = star:1,name<15%,reply:1,subject,size>=,date>=
column-star = {{if .IsFlagged}}★{{end}}
column-name = {{if eq .Role "sent"}}{{.To | names | join ", "}}{{else}}{{.From | names | join ", "}}{{end}}
column-reply = {{if .IsReplied}}{{end}}
column-subject = {{.ThreadPrefix}}{{.Subject}}
column-size = {{if .HasAttachment}}📎 {{end}}{{humanReadable .Size}}
column-date = {{.DateAutoFormat .Date.Local}}
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Koni Marti <koni.marti@gmail.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Use the template interface consistently. Before, we have exported the
state.TemplateData struct and used it in most places instead of the
models.TemplateData interface. This lead to some inconsistencies, i.e.
Role() has been defined on the exported struct but not on the interface.
Unexport the state.TemplateData struct, add a DataSetter interface to
set the data needed for the template data and call the Data() method
which returns a models.TemplateData interface when the template data is
needed.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
| |
Align the completion popover with the actual completion location on the
textinput line.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fix cursor index after stemming and reset it to the position where the
completion should occur. Only stem to add more information and not
remove any user input.
Stemming is activated on the textinput line when the user presses the
Tab key. The idea of stemming is to adjust the textinput line to the
common ground (="the stem") of the completions options.
When the stemmed input line is set, however, the cursor will be moved to
the end of the line if there is a text part on the right side of the
cursor where the completion should occur. Another Tab press will
activate the onStem function again, which then removes the right part of
the text input leading to the loss of the user input.
This can be prevented by moving the cursor to the place of the
completion after stemming.
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Expand and complete template code. The exline does understand template
code and can evaluate it. With this patch, the completion systems
supports writing the templates by showing the available template data
fields and template functions. Pressing <Tab> after }} will show the
evaluated template in the completion menu. Complex template code, such
as if-else statements work as well.
Examples:
:filter -f {{<Tab>
will show the possible template data fields and functions
:filter -f {{index (.To|email) 0}}<Tab>
will show the value of the template expression in the completion list
Pressing <Tab> twice after a completed template expression will
substitute the expression with its value.
:{{if match .Folder "INBOX"}}check-mail{{else}}cf INBOX{{end}}
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The msgstore trims the uid list when a message was deleted. It does so
whether the message is in the message store or not. If the message was
already deleted and a MessagesDeleted is received, the store will be
trimmed regardless. This can cause spurious emails to be removed from
the msgstore due to a race condition with the fs watcher / imap update
channel. When a message is deleted, the UI will received two
MessagesDeleted and in some cases trim the list, removing too many
emails.
Fix the handling of deleted messages so that the uid list is rebuilt of
all messages except the deleted ones specifically.
Reported-by: Drew Devault <sir@cmpwn.com>
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Tested-by: Inwit <inwit@sindominio.net>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When calling ui.QueueRedraw() and a redraw is currently in progress, the
redraw int value still holds REDRAW_PENDING since it is updated once the
redraw is finished. This can lead to incomplete screen redraws on the
embedded terminal.
Even changing the redraw value before starting to redraw is exposed to
races. Use a single atomic int to represent the state of the UI so that
there cannot be any confusion.
Rename the constants to make them less confusing.
Fixes: b148b94cfe1f ("ui: avoid duplicate queued redraws")
Reported-by: Jason Cox <dev@jasoncarloscox.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Jason Cox <dev@jasoncarloscox.com>
|
|
|
|
|
|
|
|
|
| |
No need to queue multiple nil messages to force multiple redraws. Only
one is required. When the screen is redrawn, clear the queued redraw
flag.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A lot of libraries are starting to use generics (introduced in go 1.18).
Restricting aerc on 1.17 prevents us from updating our dependencies.
Since 1.18 is a major milestone, it has a chance to remain supported for
a while.
Update the minimum go version to 1.18. Run go mod tidy -compat=1.18.
Update our CI to run on 1.18.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
|
| |
Add .Role as a template field for use in distinguishing between
mailboxes with a given IANA role, or custom role defined by aerc
("query" for notmuch queries, for example).
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry<robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
| |
Store the Directory RUE counts on the Directory data model. Use
DirectoryInfo messages to update the Directory model. Access Directories
via the dirlist instead of via the msgstore. Remove unused fields on
DirectoryInfo, all backends now give accurate counts.
Move refetch logic into dirlist
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry<robin@jarry.cc>
|
|
|
|
|
|
|
|
| |
Use the dirstore to store models.Directory data structures. This will be
used in subsequent commits for accessing directory data.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
ListDirectories is called when connecting, reconnecting, and
creation/deletion of a directory. The code is not in the same style as
other areas of aerc. Refactor to match coding style of the rest of aerc
by creating an Update function which handles necessary updates in the
dirlist. This style does not use a callback, making it clearer what is
happening in the message flow, and operates similar to how the msgstore
receives updates.
Use a map in the dirstore to reduce duplicate storage of directory
names. Directly add or remove directories from the map when created /
deleted to prevent a new ListDirectories message, and a flash of the UI.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Create msgstores when a types.Directory message is received. This
removes a quirk from the IMAP worker that msgstores are created on the
first DirectoryInfo, and updated on the second. This path requires three
messages in order to get an updated message store. By creating from
types.Directory, we ensure that any subsequent DirectoryInfo can be
routed to a msgstore.
Remove the field DirInfo from the msgstore initializer, it isn't needed
at initialization and isn't available with this refactor.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Use the Backend interface to report Backend capabilities. Previously,
these were reported via a DirectoryInfo message, however they have
nothing to do with a directory and should be reported directly by the
backend. Add Capabilities method to Backend interface, satisfy this in
each backend, and use it on the UI side.
Remove Caps field from DirectoryInfo
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry<robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fetching the message list is done in a convoluted way. The UI receives a
DirectoryInfo message, which creates a message store. It then receives a
second DirectoryInfo (an oddity from the IMAP worker), and this
DirectoryInfo is passed to the message store which then requests a fetch
of the message list via store.Sort.
Use the OpenDirectory done response to tell the message store to fetch
messages. This makes the code easier to follow, and does not rely on
quirks from the IMAP worker.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
This is mostly a revert of commit ae4d742c5a90 ("templates: fix layered
fg & bg color for inline styles").
As it turns out, context colors (msglist_selected, msglist_marked,
msglist_deleted, etc.) need to have priority over inline colors.
Otherwise strange and confusing results occur.
Reported-by: Skejg <grolleman@zoho.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Another attempt at fixing the high CPU usage when terminal tabs are
running interactive tui applications and the message list tab is
selected.
There are cases where a terminal widget can be visible but not focused
(composer, message viewer, attachment selector, etc.). Define a new
Visible interface with a single Show() method. Call that method when
changing tabs to make sure that terminal widget content events only
trigger redraws when they are visible.
Fixes: 382aea4a9426 ("terminal: avoid high cpu usage when not focused")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Koni Marti <koni.marti@gmail.com>
|
|
|
|
|
|
|
|
|
|
| |
Add a hook to run when aerc shuts down. The environment is supplemented
with the duration aerc was alive for.
References: https://todo.sr.ht/~rjarry/aerc/136
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
|
|
|
| |
Add a hook to run when aerc starts up. The environment is supplemented
with aerc version and the path to its binary.
References: https://todo.sr.ht/~rjarry/aerc/136
References: https://todo.sr.ht/~rjarry/aerc/139
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Deprecate triggers and replace them with hooks. Now that aerc supports
running arbitrary ex commands over IPC, it is possible to run internal
aerc commands *and* shell commands via external shell scripts. Hooks
only allow running shell commands. Hooks info is passed via environment
variables.
Implements: https://todo.sr.ht/~rjarry/aerc/136
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
| |
Rework how tabs are closed. Change the aerc.RemoveTab and
aerc.ReplaceTab functions to accept a new boolean argument. If true,
make sure to close the tab content.
Signed-off-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The logic was inverted. The style argument is actually the "under" layer
style. Each character in the RuneBuffer style must be applied on *top*
of it, not the other way around.
Use colors from style and override them with each character's colors if
they are set. Keep attributes handling unchanged.
Fixes: ab8f433e1739 ("templates: allow layered fg & bg color for inline styles")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Some user agents deliberately generate non-standard
message identifier lists in In-Reply-To and References headers.
Instead of failing silently, aerc now falls back to a desperate parser
scavaging whatever looking like <id-left@id-right>.
As the more liberal parser being substituted with, References header
are now stored for IMAP not only when there's a parsing error.
Fixes: 31d2f5be3cec ("message-info: add explicit References field")
Signed-off-by: Nguyễn Gia Phong <mcsinyx@disroot.org>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
| |
Allow wild cards for MIME types like in filters.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
|
| |
Provide a way to configure link openers. Based on the URL mime type:
x-scheme-handler/$scheme.
Signed-off-by: Kirill Chibisov <contact@kchibisov.com>
Signed-off-by: Robin Jarry <robin@jarry.cc>
Tested-by: Bence Ferdinandy <bence@ferdinandy.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add .StyleSwitch that takes a string and an arbitrary number of cases
(regexp, style). Reuse some of the constructs introduced by previous
commit.
The style of the first regular expression that matches will be applied.
If the string does not match any of the expressions, it will be left
as-is.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
| |
This allows much shorter templates.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Add a match function that returns true if a string matches the provided
regular expression. The compiled regular expressions are cached in
a sync.Map to avoid repetitive compilations of the same expressions.
Caveat: if the user mixes the arguments order, it may cause the cache to
consume a lot of memory filled with garbage regular expression objects.
Ideally, we would need to limit the size of this cache and/or use a LRU
cache implementation. Maybe someday?
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
| |
In preparation for .StyleMatch put the content first, followed by the
style name.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
| |
Document .SubjectBase. Fix its value along the way. Do not reuse
d.Subject() which may be empty if d.threadSameSubject is true.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
| |
Extract {{.ThreadPrefix}} from {{.Subject}} so that the prefix can be
styled in a different color.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
| |
If a user style has no fg and/or no bg color defined, use the color from
the underlying style.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
| |
It would be nicer if aerc behaved the same way most other tools behave
in that no news is good news.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In order to make automation easier, it's useful to be able to send
commands to aerc via IPC. This can be done by calling the aerc binary
followed by a colon and the command to run. For example:
aerc :read && aerc :remark && aerc :archive month
Security to ensure no malicious commands are run is deferred to the
user. By default the socket is only writable by the user. This is
considered sufficient as the potential harm an attacker gaining
write-access to a user's session can cause is significantly greater than
"can delete some emails".
To ensure users with an according threat model, it is possible to
disable command IPC. mailto-handling is unaffected even though it works
over IPC as it is absolutely non-destructive.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
| |
Currently, every function has to be mapped to the according handler with
our god-object. To make adding new handlers require less changes, change
this mapping into an interface that is satisfied by *widgets.Aerc
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
In overhauling the IPC, it has become necessary to switch to a more
extendable message format, to ensure more complex commands can be sent.
Messages have the following basic structure and must not contain
linebreaks, as these are used to delimit separate messages from one
another.
{"arguments": ["mailto:moritz@poldrack.dev"]}
The responses have the following structure:
{"error": "epic fail"}
If the IPC request was successful, "error" will be empty.
{"error": ""}
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
There are several //TODO comments in the socket package, these should be
fixed before expanding it.
Put send logic into it's own file and rename receiver code.
Fix the rather inelegant error handling when shutting down the server.
Make sure to close sockets.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Signed-off-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
|
| |
The current model of files dumped into lib does not follow the general
advice not to have "util" classes. Naming the package "lib" does not
change that it is a random assortments of functions that have some
utility.
Extracts socket functionality into it's own package.
Signed-off-by: Moritz Poldrack <git@moritz.sh>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
| |
When a column has ALIGN_CENTER and the number of white space character
of padding is not a multiple of two, the last cell(character) is not
padded and that can cause coloring glitches. Make sure to pad all the
way.
Fixes: 49de9b09cacc ("ui: parse strings for ansi styles")
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Allow custom user-defined styles in a styleset. The styles can take any
name, and must be under the [user] ini section. All attributes apply to
user defined styles.
Example:
[user]
red.fg=red
red.bold=true
Add a .Style function which accepts the name of a user-defined style and
applies it to the string.
{{.Style "red" "foo"}}
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
| |
Parse UI strings for ANSI styles. If there are styles in the string, use
those as the display style in tcell. This is in preparation for a
template function which can apply arbitrary styles to UI elements.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
|
|
|
|
|
|
|
|
|
|
|
| |
Replace dirlist-format with two settings: dirlist-left & dirlist-right.
These two settings take aerc-templates(7) and may be left empty.
Add automatic translation of dirlist-format to these new settings.
Display a warning on startup if dirlist-format has been converted.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
| |
This will be used in the dirtree-format replacement by templates.
Signed-off-by: Robin Jarry <robin@jarry.cc>
Acked-by: Tim Culverhouse <tim@timculverhouse.com>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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>
|
|
|
|
|
|
|
|
| |
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>
|