Is there something like "awful.client.focus.global_byidx()"? - lua

I have two monitors and I would like to change client focused by shortcut. Right now I have awful.client.focus.byidx(1) but it only changes clients on one monitor. I know there is awful.client.focus.global_bydirection("right") that works on multiple screens but it only goes to one direction and it stops working when get to last client. I like awful.client.focus.byidx(1) behavior which loops through all clients, so from the last client it goes to the first one.
I would like to use a hybrid between: going through clients as in awful.client.focus.byidx(1) but on all monitors/screens like awful.client.focus.global_bydirection("right") does. Is there a function that would have that behavior so I could use it? If not, do you know how could I achieve that goal?

First, let's look at how awful.client.focus.byidx is implemented.
The function itself calls awful.client.next and then focused the returned client, if any is found:
https://github.com/awesomeWM/awesome/blob/9781f14b105ee700c5bca339bf49bb52d2cca4b5/lib/awful/client/focus.lua#L65-L71
awful.client.next is implemented here: https://github.com/awesomeWM/awesome/blob/9781f14b105ee700c5bca339bf49bb52d2cca4b5/lib/awful/client.lua#L262-L284
It does the following:
line 263: Get the currently focused client
line 267: Get all visible clients on the screen of the visible client
line 270-274: Filter out unfocusable clients from the list
line 277 - 278: Find the focused client in the resulting list
line 280: Get the client at the wanted offset and return it
So, your request sounds like you only need to change one step here: Get the list of all visible clients instead of only those at the currently focused screen.
To get that list, you need to call awful.client.visible with nil instead of a specific screen.
Untested code:
function next_global(i, sel, stacked)
sel = sel or client.focus
if not sel then return end
local cls = awful.client.visible(nil, stacked)
local fcls = {}
for _, c in ipairs(cls) do
if awful.client.focus.filter(c) or c == sel then
table.insert(fcls, c)
end
end
cls = fcls
for idx, c in ipairs(cls) do
if c == sel then
return cls[gears.math.cycle(#cls, idx + i)]
end
end
end
function focus_byidx_global(i, c)
local target = next_global(i, c)
if target then
target:emit_signal("request::activate", "client.focus.byidx", {raise=true})
end
end
I don't know which version of AwesomeWM you are using. If in doubt, look at the installed files in /usr/share/awesome/lib/ and copy the code from there, then change it.
(A little more ugly solution would be something like the following, even though it requires less code; I leave it as an exercise to the reader to figure out what this does, but note that this "breaks stuff" in case a Lua error occurs and the monkey-patching becomes permanent)
function focus_byidx_global(i, c)
local old = awful.client.visible
awful.client.visible = function(_, s) return old(nil, s) end
awful.client.focus.byidx(i, c)
awful.client.visible = old
end

Related

how is a function navigating through fields of a table

i already asked this question on stackoverflow and accepted an answer i think i did not really understand the answer and i got some more question, im embarrassed to necro it so im creating a new question
im learning lua and got to metatable part, in this example
local tb = {}
local meta = {}
function tb.new(s)
local super = {}
super.s = s
setmetatable(super,meta)
return super
end
function tb.add(s1,s2)
return s1.s..s2.s
end
meta.__add = tb.add
f= tb.new("W")
t= tb.new("E")
print(f+t)
when compiler gets tof = tb.new("W")
i think this happens
function tb.new("W") super.W = W return setmetatable(super,meta) return super end
so
print(f+t)
looks like
print(super+super)
how does
tb.add(super,super)
find the fields of super table using
return s1.s..s2.s
also as the
tb.new
function is called twice and
setmetatable(super,meta)
happens twice is there any difference between the first and second iteration? if any of the above are incorrect please correct me.
when compiler gets tof = tb.new("W") i think this happens function tb.new("W") super.W = W return setmetatable(super,meta) return super end
No. It's more like super['s'] = 'W'. That's how dot notation works. I hope that clarifies how Lua "finds the fields" later.
as the tb.new function is called twice and setmetatable(super,meta) happens twice is there any difference between the first and second iteration?
They're different, because the super variable is a new table each time. Any time you see {} (a table constructor), whether empty or not, it's creating an entirely new table. meta, however, is still the same table, because it only gets a table constructor once, outside of any function.

Lua - table won't insert from function

I have a Lua function where I build a table of value and attempt to add it to a global table with a named key.
The key name is pulled from the function arguments. Basically, it's a filename, and I'm pairing it up with data about the file.
Unfortunately, the global table always comes back nil. Here's my code: (let me know if you need to see more)
(Commented parts are other attempts, although many attempts have been deleted already)
Animator = Class{}
function Animator:init(atlasfile, stringatlasfriendlyname, totalanimationstates, numberofframesperstate, booleanstatictilesize)
-- Define the Animator's operation mode. Either static tile size or variable.
if booleanstatictilesize ~= false then
self.isTileSizeStatic = true
else
self.isTileSizeStatic = false
end
-- Define the total animation states (walking left, walking right, up down, etc.)
-- And then the total frames per state.
self.numAnimationStates = totalanimationstates or 1
self.numAnimationFrames = numberofframesperstate or 2
-- Assign the actual atlas file and give it a programmer-friendly name.
self.atlasname = stringatlasfriendlyname or removeFileExtension(atlasfile, 'animation')
generateAnimationQuads(atlasfile, self.atlasname, self.numAnimationStates, self.numAnimationFrames)
end
function generateAnimationQuads(atlasfile, atlasfriendlyname, states, frames)
spriteWidthDivider = atlasfile:getWidth() / frames
spriteHeightDivider = atlasfile:getHeight() / states
animationQuadArray = generateQuads(atlasfile, spriteWidthDivider, spriteHeightDivider)
animationSetValues = {atlasarray = animationQuadArray, width = spriteWidthDivider, height = spriteHeightDivider}
--gAnimationSets[#gAnimationSets+1] = atlasfriendlyname
gAnimationSets[atlasfriendlyname] = animationSetValues
--table.insert(gAnimationSets, atlasfriendlyname)
end
Note: when using print(atlasfriendlyname) and print(animationSetValues), neither are empty or nil. They both contain values.
For some reason, the line(s) that assign the key pair to gAnimationSets does not work.
gAnimationSets is defined a single time at the top of the program in main.lua, using
gAnimationSets = {}
Animator class is called during the init() function of a character class called Bug. And the Bug class is initialized in the init() function of StartState, which extends from BaseState, which simply defines dummy init(), enter(), update() etc. functions.
StartState is invoked in main.lua using the StateMachine class, where it is passed into StateMachine as a value of a global table declared in main.lua.
gAnimationSets is declared after the table of states and before invoking the state.
This is using the Love2D engine.
Sorry that I came here for help, I've been picking away at this for hours.
Edit: more testing.
Trying to print the animationQuadArray at the index gTextures['buganimation'] always returns nil. Huh?
Here's gTextures in Main.lua
gTextures = {
['background'] = love.graphics.newImage('graphics/background.png'),
['main'] = love.graphics.newImage('graphics/breakout.png'),
['arrows'] = love.graphics.newImage('graphics/arrows.png'),
['hearts'] = love.graphics.newImage('graphics/hearts.png'),
['particle'] = love.graphics.newImage('graphics/particle.png'),
['buganimation'] = love.graphics.newImage('graphics/buganimation.png')
}
Attempting to return gTextures['buganimation'] returns a file value as normal. It's not empty.
My brain is so fried right now I can't even remember why I came to edit this. I can't remember.
Global table in Main.lua, all other functions can't access it.
print(gTextures['buganimation']) works inside the function in question. So gTextures is absolutely accessible.
Table isn't empty. AnimationSetValues is not empty.
I'm adding second answer because both are correct in context.
I ended up switching IDE's to VS Code and now the original one works.
I was originally using Eclipse LDT with a Love2D interpreter and in that environment, my original answer is correct, but in VS Code, the original is also correct.
So Dimitry was right, they are equivalent, but something about my actual Eclipse setup was not allowing that syntax to work.
I switched to VS Code after I had another strange syntax problem with the interpreter where goto syntax was not recognized and gave a persistent error. The interpreter thought goto was the name of a variable.
So I switched, and now both things are fixed. I guess I just won't use LDT for now.
Solution: Lua syntax. Brain Fry Syndrome
I wrote:
animationSetValues = {atlasarray = animationQuadArray, width = spriteWidthDivider, height = spriteHeightDivider}
Should be:
animationSetValues = {['atlasfile']=atlasfile, ['atlasarray']=animationQuadArray, ['width']=spriteWidthDivider, ['height']=spriteHeightDivider}
Edit: I'm fully aware of how to use answers. This was posted here to reserve my spot for an answer so I could edit it later when I returned back home, which is exactly what I'm doing right now. I'll keep the old post for archival purposes.
Original:
I solved it. I apologize for not posting the solution right now. My brain is melted into gravy.
I will post it tomorrow. Just wanted to "answer" saying no need to help. Solved it.
Solution is basically, "oh it's just one of those Lua things". Wonderful. I'm having so much fun with this language - you can tell by my blank expression.
From the language without line endings or brackets, but forced print parentheses... ugh. I'm going back to C# when this class is done.

Adding labels to my programming language

Actually I am writting a programming language in Lua. It was quite fun. I've wrote a bit of standard library (stack op and simple io). Then I've thought about labels. It would look like in assembly. While and for loop aren't funny in any bit so programming in that language can be quite challenging. Here are some requirements for this system:
Label stack (or array, dictionary) must be accessible from global context.
Jump instruction handler will be in separate file.
This is how my label-handling function look like:
function handleLabel(name,currentLine)
end
I have no idea how to implement this kind of magic. First I've thought about that:
LabelLineIDS = {}
Labels = {}
Labelamount = 1;
function handleLabel(name,currentLine)
LabelLineIDS[Labelamount]=currentline
Labels[Labelamount]=name
Labelamount=Labelamount+1
end
-- In file "jump.lua":
local function has_value (tab, val)
for index, value in ipairs(tab) do
if value == val then
return index
end
end
print ("Error: Label not defined.") -- Bail out.
os.exit(1)
end
local function _onlabel()
local labelName = globalparams --Globalparams variable contain parameters to each function, at the moment
--this will contain label name. It _can_ be nil.
return LabelLineIDS[has_value(Labels, labelName)]
end
CurrLine = _onlabel() --Currline - current line that get's parsed.
--1 command per one line.
But I'm unsure is this well written or even work. Can you give me idea how to parse labels in my programming language (and write jump functions)? Or if my code is pretty ok at the moment, can you help me to improve it?
Using line counter in my parser I've decided to implement gotos like we can see in BASIC. Thanks everyone for help.

World-of-Warcraft Chat Frame Filter Conflict

I have a WoW/LUA script that I am attempting to start, but it seems to conflict with the Stubby addon, which is a part of the Auctioneer addon, I believe. Here is the message I receive:
Error occured in: Stubby Count: 1 Message: Error: Original call failed
after running hooks for: ChatFrame_OnEvent Usage:
SendChatMessage(text [,type] [,language] [,targetPlayer]) Debug:
(tail call): ? [string ":OnEvent"]:1:
[string ":OnEvent"]:1
Now, the only thing that's happening in the conflicting addon is:
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY", partyMsg)
The code within partyMsg is very simple as well:
local function partyMsg(msg,author,language,lineID,senderGUID)
if (store ~= msg) then
SendChatMessage(msg,"SAY",nil,nil);
end
store = msg;
end
Is this error due to two addons both trying to filter the chat frame? If so, how can this be done? It seems odd to me that Blizzard would have such a simple and yet important concept limited to one addon.
I think I see what happened here.
The reference you were using, Events/Communication, shows only the specific parameters for a particular event, regardless of context.
The context is usually an OnEvent handler.
The ChatFrame_AddMessageEventFilter function lets you use the chat frame's OnEvent handler instead of your own for chat frame events, and has well defined parameters for filters you add.
An OnEvent handler might look like:
function Foo_OnEvent(self, event, ...)
A 'ChatFrame' filter must look like this, for the first two parameters:
function Foo_ChatFrameFilter(self, event, msg, ...)
The ChatFrame filter is specific. For OnEvent however, you can make a Lua 'handler' that doesnt care about what frame it came from:
<OnEvent>
MyEventHandler(event, ...)
</OnEvent>
For the sake of completion, I will include the entire source of this addon:
local function partyMsg(someTable,msgType,msg,user,language,...)
if (store ~= msg) then
SendChatMessage(user .. " just said: ".. msg .. " using that sneaky " .. language .. " language.");
end
store = msg;
return false;
end
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY", partyMsg)
ChatFrame_AddMessageEventFilter("CHAT_MSG_PARTY_LEADER",partyMsg)
There were a couple issues with the original code:
1) I was using WoWWiki to get my information, and first, I read it incorrectly. lineID and senderGUID are not the 4th and 5th arguments. Then, beyond this, WoWWiki is incorrect on this page in general. The correct arguments are listed above in the source. The first argument, a table, I am unsure of its purpose. In any case, this code now works fully.

Control flow in Lua

I have a problem which i suppose must be very common and most of you would have faced it.
I have written a program in lua, say main.lua which on receiving key event should modify the coordinates and display the geometry figure.
This lua code calls reg.c, where it kind of registers.
Now in reg.c i have a function engine which receives the key pressed and passes it to the lua function responsible for key handling.
But by the time key event comes, lua code is done with the registration and exits, thus the call from engine() becomes illegal memory access leading to segmentation fault.
Also i suppose we can't have lua call hanging in reg function, and call engine function from somewhere else.
Then what should be the solution, please guide me through this.
#jacob: here is the prototype of what i am trying to achieve:
function key_handler() //this function will get the latest key pressed from some other function
{
draw.image();
draw.geometry();
...
...
while(1)
{
//draw Points until some condition goes wrong
}
}
Now, once entered into key_handler, while he is busy drawing the points unless and until the failing condition occurs, i am unable to receive key pressed till that time.
I hope this explanation is much simpler and have made my point, and will help others to understand the problem.
I am really sorry, but i am not good at expressing or making others understand.
One more thing, i ahve followed the C syntax to explain, however this is completely implemented in lua
Your code snippet is still largely non-informative (ideally one should be able to just run your code in a stock Lua interpreter and see your problem). If you're describing a Lua problem, use Lua code to describe it.
However I'm beginning to see where you want to go.
The thing you need to could do is have a coroutine that's called in your key handler, which passes an argument back to your handler:
function isContinue() --just to simulate whatever function you use getting keypresses.
-- in whatever framework you're using there will probably be a function key_pressed or the like.
print('Initialize checking function')
while true do
print('Continue looping?')
local ans = io.read():match('[yY]')
local action
if not ans then
print('Do what instead?')
action = io.read()
if action:match('kill') then -- abort keychecker.
break
end
end
coroutine.yield(ans,action)
end
print('finalizing isContinue')
return nil,'STOP' -- important to tell key_handler to quit too, else it'll be calling a dead coroutine.
end
function key_handler()
local coro = coroutine.create(isContinue)
local stat,cont,action
while true do
print'Draw point'
stat,cont,action = coroutine.resume(coro)
if not stat then
print('Coroutine errored:',cont)
elseif not cont then
print('isContinue interrupted keyhandler')
print("We'll "..action.." instead.")
break
end
end
print('finalizing key_handler')
end
key_handler()
-- type something containing y or Y to continue, all else aborts.
-- when aborting, you get asked what to do instead of continuing,
--- with "kill" being a special case.
This should be self explanatory. You should probably take a good look at Programming in Lua, chapter 9: Coroutines.
The big difficulty (well, if you're not accustomed to collaborative threading) is that a coroutine should yield itself: it's not the calling function that's in charge of returning control.
Hope this helps you.

Resources