We now print the type and pointer address for recursive entries,
rather than eliding them and emitting a warning.
refs: https://github.com/wez/wezterm/pull/4336
This commit changes how lua Strings are rendered when printing
them through ValuePrinter.
Previously, we'd try to convert to a utf8 string and print the bare
string to the output. If it failed, we'd get a less than useful output;
for this example when inspecting the the `utf8` global module from
the debug overlay:
```
> utf8.charpattern
(error converting Lua string to &str (invalid utf-8 sequence of 1 bytes from index 4))
```
Now we handle the failure case and show it as a binary string using a
somewhat invented syntax; the `b"string"` syntax isn't valid in lua,
but it helps to communicate that this is a binary string:
```
> utf8.charpattern
b"[\x00-\x7f\xc2-\xfd][\x80-\xbf]*"
```
in addition, we now quote and escape unicode strings.
Previously;
```
> wezterm.target_triple
x86_64-unknown-linux-gnu
```
now:
```
> wezterm.target_triple
"x86_64-unknown-linux-gnu"
```
refs: https://github.com/wez/wezterm/pull/4336
We can now delegate to the new mlua helpers for a lot of this stuff.
We do still take first dibs on printing userdata so that we can use
our dynamic data interpretation when available, but otherwise, we
can now show reasonable information about things like builtin file
objects, and include the pointer address of things like functions
to help disambiguate them when printing them.
refs: #3849
refs: https://github.com/khvzak/mlua/issues/291
config_builder helps to make issues more visible/useful in the case
where you may have typod a config option, or otherwise assigned
an incorrect value.
I've been holding off from using UserData wrappers around things
because it is awkward to match them up with the To/FromDynamic
conversion.
This commit aims to help with that by implicitly calling the
tostring metamethod (if present) on a userdata both when printing
(so the values look reasonable in the repl) and when mapping a lua
value to a dynamic value.
Provided that the end type is try_from=String this will allow
the userdata value to be assigned as table value.
An ExecDomain is a variation on WslDomain with the key difference
being that you can control how to map the command that would be
executed.
The idea is that the user can define eg: a domain for a docker
container, or a domain that chooses to run every command in its
own cgroup.
The example below shows a really crappy implementation as a
demonstration:
```
local wezterm = require 'wezterm'
return {
exec_domains = {
-- Commands executed in the woot domain have "WOOT" echoed
-- first and are then run via bash.
-- `cmd` is a SpawnCommand
wezterm.exec_domain("woot", function(cmd)
if cmd.args then
cmd.args = {
"bash",
"-c",
"echo WOOT && " .. wezterm.shell_join_args(cmd.args)
}
end
-- you must return the SpawnCommand that will be run
return cmd
end),
},
default_domain = "woot",
}
```
This commit unfortunately does more than should go into a single
commit, but I'm a bit too lazy to wrangle splitting it up.
* Reverts the nil/null stuff from #2177 and makes the
`ExtendSelectionToMouseCursor` parameter mandatory to dodge
a whole load of urgh around nil in table values. That is
necessary because SpawnCommand uses optional fields and the
userdata proxy was making that a PITA.
* Adds some shell quoting helper functions
* Adds ExecDomain itself, which is really just a way to
to run a callback to fixup the command that will be run.
That command is converted to a SpawnCommand for the callback
to process in lua and return an adjusted version of it,
then converted back to a command builder for execution.
refs: https://github.com/wez/wezterm/issues/1776
ee5206db50 attempted to fix this by
replacing all DynValue::Null values with a special null userdata.
However, a consequence of that is that it broke:
```
window:get_config_overrides() or {}
```
because a userdata is always true, even if it represents a null value.
This commit fixes that case by being selective with the userdata usage:
we only use it when converting the value portion of a table key/value
pair.
refs: #2177
refs: #2200
In #2177 we found that one of the examples that tries to use
the default initialization was failing. The root cause is that
we were constructing a value like:
`{ExtendSelectionToMouseCursor=nil}`
which is effectively the same as:
`{}`
but that has no information on the enum variant name.
This commit avoids mapping DynValue::Null to LuaValue::Nil
and instead uses a light user data nullptr value.
That allows the structure to round trip correctly.
refs: #2177
In https://github.com/wez/wezterm/issues/2170 a config like this was
used:
```lua
return {
keys = {
{key="e", ...},
copy_Mode = {
{key="a", ...}
}
}
}
```
instead of the intended:
```lua
return {
keys = {
{key="e", ...},
},
key_tables={
copy_Mode = {
{key="a", ...}
}
},
}
```
This commit makes an attempt at detecting when non-numeric, or sparse
numeric, keys are used for an array style table and generates an error.
The error isn't ideal, but it at least indicates that something is
wrong:
```
Configuration Error: Error converting lua value returned by script
/tmp/whoops.lua to Config struct: error converting Lua table to Config
(error converting Lua table to value (while processing "keys": error
converting Lua string to numeric array index (Unexpected key "copy_mode"
for array style table)))
```
refs: #2170
Avoid using serde for mapping between Lua and Rust for the `Config`
struct.
This improves the build speed of the config crate by 2x; it goes down
from 30 seconds to 9 seconds on my 5950x.
printing _G would still sometimes overflow for me.
The code a0b8d2196a wasn't sufficient so
beef it up both with a hash set to remember all visited refs as well
as a depth limit of 128, which should be deep enough for most practical
purposes.
This commit expands on the prior commits to introduce the concept
of per-window configuration overrides.
Each TermWindow maintains json compatible object value holding
a map of config key -> config value overrides.
When the window notices that the config has changed, the config
file is loaded, the CLI overrides (if any) are applied, and then
finally the per-window overrides, before attempting to coerce
the resultant lua value into a Config object.
This mechanism has some important constraints:
* Only data can be assigned to the overrides. Closures or special
lua userdata object handles are not permitted. This is because
the lifetime of those objects is tied to the lua context in which
they were parsed, which doesn't really exist in the context of
the window.
* Only simple keys are supported for the per-window overrides.
That means that trying to override a very specific field of
a deeply structured value (eg: something like `font_rules[1].italic = false`
isn't able to be expressed in this scheme. Instead, you would
need to assign the entire `font_rules` key. I don't anticipate
this being a common desire at this time; if more advance manipulations
are required, then I have some thoughts on an event where arbitrary
lua modifications can be applied.
The implementation details are fairly straight-forward, but in testing
the two examplary use cases I noticed that some hangovers from
supporting overrides for a couple of font related options meant that the
window-specific config wasn't being honored. I've removed the code that
handled those overrides in favor of the newer more general CLI option
override support, and threaded the config through to the font code.
closes: #469closes: #329
This commit adds very basic first passes at representing the Pane
and GuiWindow types in lua script.
The `open-uri` event from 9397f2a2db
has been redefined to receive `(window, pane, uri)` parameters
instead of its prior very basic `uri` parameter.
A new key assignment `wezterm.action{EmitEvent="event-name"}` is
now available that allows a key binding assignment to emit an arbitrary
event, which in turn allows for triggering an arbitrary lua callback
in response to a key or mouse click.
`EmitEvent` passes the `(window, pane)` from the triggering window and
pane as parameters.
Here's a brief example:
```lua
local wezterm = require 'wezterm';
wezterm.on("my-thingy", function(window, pane)
local dims = pane:get_dimensions();
wezterm.log_error("did my thingy with window " .. window:window_id() ..
" pane " .. pane:pane_id() .. " " .. dims.cols .. "x" .. dims.viewport_rows);
window:perform_action("IncreaseFontSize", pane);
end)
return {
keys = {
{key="E", mods="CTRL", action=wezterm.action{EmitEvent="my-thingy"}},
}
}
```
refs: #223
refs: #225