wez / wezterm

A GPU-accelerated cross-platform terminal emulator and multiplexer written by @wez and implemented in Rust
https://wezfurlong.org/wezterm/
Other
17.28k stars 781 forks source link

`wezterm.plugin.require()` errors when there's a `.` in the directory name #3194

Closed nekowinston closed 1 year ago

nekowinston commented 1 year ago

What Operating System(s) are you seeing this problem on?

Linux X11

Which Wayland compositor or X11 Window manager(s) are you using?

i3 version 4.21.1 (2022-10-24) on NixOS

WezTerm version

2d05f8f1f24db6370f0791e9ec3a98ad38cf8b4d

Did you try the latest nightly build to see if the issue is better (or worse!) than your current version?

Yes, and I updated the version box above to show the version of the nightly that I tried

Describe the bug

I tried to make a plugin that conforms to the experimental plugin spec.

When I'm loading my plugin as https://github.com/nekowinston/wezterm.bar, I'm getting the following stack traceback:

callback error
stack traceback:
        [C]: in field 'require'
        [string "/home/winston/.config/wezterm/wezterm.lua"]:34: in main chunk
caused by: runtime error: module
'httpssCssZssZsgithub.comsZsnekowinstonsZswezterm.bar' not found:
        no field package.preload['httpssCssZssZsgithub.comsZsnekowinstonsZswezterm.bar']
        no file '/home/winston/.config/wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar.lua'
        no file '/home/winston/.config/wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar/init.lua'
        no file '/run/user/1000/wezterm/plugins/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar/plugin/init.lua'
        no file '/home/winston/.wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar.lua'
        no file '/home/winston/.wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar/init.lua'
        no file '/usr/local/share/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar.lua'
        no file '/usr/local/share/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar/init.lua'
        no file '/usr/local/lib/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar.lua'
        no file '/usr/local/lib/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm/bar/init.lua'
        no file './httpssCssZssZsgithub/comsZsnekowinstonsZswezterm/bar.lua'
        no file './httpssCssZssZsgithub/comsZsnekowinstonsZswezterm/bar/init.lua'

        can't load C modules in safe mode
stack traceback:
        [C]: in ?
        [C]: in function 'require'
        [C]: in field 'require'
        [string "/home/winston/.config/wezterm/wezterm.lua"]:34: in main chunk

This also happens when using a local directory, named wezterm.bar:

local wezterm = require("wezterm")

local c = wezterm.config_builder()

c.color_scheme = "Catppuccin Mocha"
wezterm.plugin.require("/home/winston/Code/wezterm.bar").apply_to_config(c)

return c
callback error
stack traceback:
        [C]: in field 'require'
        [string "/home/winston/.config/wezterm/wezterm.lua"]:34: in main chunk
caused by: runtime error: module 'sZshomesZswinstonsZsCodesZswezterm.bar'
not found:
        no field package.preload['sZshomesZswinstonsZsCodesZswezterm.bar']
        no file '/home/winston/.config/wezterm/sZshomesZswinstonsZsCodesZswezterm/
bar.lua'
        no file '/home/winston/.config/wezterm/sZshomesZswinstonsZsCodesZswezterm/
bar/init.lua'
        no file '/run/user/1000/wezterm/plugins/sZshomesZswinstonsZsCodesZswezterm/
bar/plugin/init.lua'
        no file '/home/winston/.wezterm/sZshomesZswinstonsZsCodesZswezterm/bar.lua'
        no file '/home/winston/.wezterm/sZshomesZswinstonsZsCodesZswezterm/bar/
init.lua'
        no file '/usr/local/share/lua/5.4/sZshomesZswinstonsZsCodesZswezterm/bar.lua'
        no file '/usr/local/share/lua/5.4/sZshomesZswinstonsZsCodesZswezterm/bar/
init.lua'
        no file '/usr/local/lib/lua/5.4/sZshomesZswinstonsZsCodesZswezterm/bar.lua'
        no file '/usr/local/lib/lua/5.4/sZshomesZswinstonsZsCodesZswezterm/bar/
init.lua'
        no file './sZshomesZswinstonsZsCodesZswezterm/bar.lua'
        no file './sZshomesZswinstonsZsCodesZswezterm/bar/init.lua'

        can't load C modules in safe mode
stack traceback:
        [C]: in ?
        [C]: in function 'require'
        [C]: in field 'require'
        [string "/home/winston/.config/wezterm/wezterm.lua"]:34: in main chunk

To Reproduce

Use the minimal config I provided.

Configuration

Minimal config:

local wezterm = require("wezterm")

local c = wezterm.config_builder()
-- the plugin is currently made for Catppuccin
c.color_scheme = "Catppuccin Mocha"

wezterm.plugin
  .require("https://github.com/nekowinston/wezterm.bar")
  .apply_to_config(c)

return c

Expected Behavior

The same behavior as when using wezterm-bar for the name - the plugin loading and applying to the config.

Logs

No response

Anything else?

When I'm using a local path and the folder is named wezterm-bar, it works!

local wezterm = require("wezterm")

local c = wezterm.config_builder()

c.color_scheme = "Catppuccin Mocha"
wezterm.plugin.require("/home/winston/Code/wezterm-bar").apply_to_config(c)

return c
nekowinston commented 1 year ago

I just renamed my plugin repository to wezterm-bar to see if that fixes the remote part of the issue:

> wezterm.plugin.list()
[
    {
        "component": "httpssCssZssZsgithub.comsZsnekowinstonsZswezterm-bar",
        "url": "https://github.com/nekowinston/wezterm-bar",
    },
]

Which clones it as:

> tree /run/user/1000/wezterm/plugins/
/run/user/1000/wezterm/plugins/
└── httpssCssZssZsgithub.comsZsnekowinstonsZswezterm-bar
    ├── plugin
    │   └── init.lua
    └── README.md

And I'm still getting the same error:

callback error
stack traceback:
        [C]: in field 'require'
        [string "/home/winston/.config/wezterm/wezterm.lua"]:33: in main chunk
caused by: runtime error: module
'httpssCssZssZsgithub.comsZsnekowinstonsZswezterm-bar' not found:
        no field package.preload['httpssCssZssZsgithub.comsZsnekowinstonsZswezterm-
bar']
        no file '/home/winston/.config/wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar.lua'
        no file '/home/winston/.config/wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar/init.lua'
        no file '/run/user/1000/wezterm/plugins/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar/plugin/init.lua'
        no file '/home/winston/.wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar.lua'
        no file '/home/winston/.wezterm/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar/init.lua'
        no file '/usr/local/share/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar.lua'
        no file '/usr/local/share/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar/init.lua'
        no file '/usr/local/lib/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar.lua'
        no file '/usr/local/lib/lua/5.4/httpssCssZssZsgithub/
comsZsnekowinstonsZswezterm-bar/init.lua'
        no file './httpssCssZssZsgithub/comsZsnekowinstonsZswezterm-bar.lua'
        no file './httpssCssZssZsgithub/comsZsnekowinstonsZswezterm-bar/init.lua'

        can't load C modules in safe mode
stack traceback:
        [C]: in ?
        [C]: in function 'require'
        [C]: in field 'require'
        [string "/home/winston/.config/wezterm/wezterm.lua"]:33: in main chunk

I think it also impacts the dot in the httpssCssZssZsgithub.com part.

miversen33 commented 1 year ago

This is not a wezterm issue, this is a lua "issue".

Lua uses . as the delimiter in module pathing (similar to python, java, etc). So what is happening here is lua is attempting to import the module bar from the module wezterm (wezterm.bar) which is not what you want to tell it to do.

The "fix" is to load your module in a different manner.

EG: https://stackoverflow.com/a/59597110/2104990

require looks for files using loaders, you can add a custom loader by inserting the function into package.loaders.

Your custom loader might look like this:

local function load(modulename)
  local errmsg = ""
  for path in string.gmatch(package.path, "([^;]+)") do
    local filename = string.gsub(path, "%?", modulename)
    local file = io.open(filename, "rb")
    if file then
      -- Compile and return the module
      return assert(loadstring(assert(file:read("*a")), filename))
    end
    errmsg = errmsg.."\n\tno file '"..filename.."' (checked with custom loader)"
  end
  return errmsg
end

table.insert(package.loaders, 2, load) -- this will run before the standard loader, if you want it to
                                       -- run after you can call table.insert(package.loaders, load)

Related: LuaModulesLoader

nekowinston commented 1 year ago

Yes, I know why it's happening, I'm suggesting that the clone function of wezterm.plugin.update_all() changes the path (on remote urls, since it's working when sourced locally and there is no dot), so that it (for example) replaces . with _. https://github.com/wez/wezterm/blob/e4ae8a844d8feaa43e1de34c5cc8b4f07ce525dd/lua-api-crates/plugin/src/lib.rs#L243-L255

From the commit I linked to for the experimental spec:

Brief usage notes here:

local wezterm = require 'wezterm'
local a_plugin = wezterm.plugin.require "https://github.com/owner/repo"

local config = wezterm.config_builder()

a_plugin.apply_to_config(config)

return config

The referenced repo is expected to have a plugin/init.lua file, and by convention, return a module that exports an apply_to_config function that accepts at least a config builder parameter, but may pass other parameters, or a lua table with a config field that maps to a config build parameter. [...] wezterm.plugin.require will then perform require "NAME", and since the default package.path now includes the appropriate location from the runtime dir, the module should load.

github-actions[bot] commented 1 year ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.