Search code examples
luascopemetaprogrammingdeclarationawesome-wm

What does this piece of lua code from awesome wm do?


Take a look at this code:

local urgent = {}

local capi =
{
    client = client,
}

local client
do
    client = setmetatable({}, {
        __index = function(_, k)
            client = require("awful.client")
            return client[k]
        end,
        __newindex = error -- Just to be sure in case anything ever does this
    })
end

I'm having trouble understanding what it does. It's from the awesome-wm project. These are the things I'm having trouble understanding:

  1. client = client in the declaration of capi
  2. setmetatable stuff inside do-end

Solution

    1. client = client in the declaration of capi

    This is defining what portion of the capi is available in this file's scope, If you look at the client.lua file you will see that the capi defined in it has client, mouse, screen, and awesome.

    For each item defined in the capi table there is a corresponding .c file. These files define objects such as client. urgent.lua has visibility of that object, likely it is a global variable, that is how we can set client = client the second client refers to the global variable.

    Here is an example of 2 files:

    main.lua

    bar = "Hello World!"
    
    local foo = require('foo')
    
    print(foo.bar)
    

    foo.lua

    local foo = {
        bar = bar
    }
    return foo
    

    The print function in main.lua will result in Hello World!

    1. setmetatable stuff inside do-end

    Here by warping the setmetatable in a do-end block the code is executing in a restricted scope. This is normally done to contain the block's local variables so that they do not persist after the code's execution.

    That said that is not the purpose of this block as the block has no local variables. As I see it, the blocking is simply to show that the object being modified is the local variable of client and not the global variable of client.

    Additionally the metatable here is used to prevent circular dependency loops, this is mentioned comments in some of the places where similar code appears in the project, such as client.lua where local screen is defined.