How to get all of the properties of window in NeoVim? - lua

I want to take a look at all of the options which have been set to some window
current_window = vim.api.nvim_get_current_win()
vim.wo[current_window].wrap = true
Trying just to call print(vim.inspect(current_window)) gives me this:
{
<metatable> = {
__index = <function 1>,
__newindex = <function 2>
}
}
Trying to get size of the table gives me zero:
local v = vim.wo[current_window]
print(#v) -- result is 0
But at the same time this property exists. The next snippet gives me true
print(vim.inspect(vim.wo[current_window].wrap)) -- result is true
How can I extract all of the window options?

Type :h options.txt
Type /local to window and press enter
Press n or N to go forward and backward
Make sure you've read :h help-summary and :h user-manual

Came to the next snippet, which will print out options for the current window in neovim
local all_options = api.nvim_get_all_options_info()
local win_number = api.nvim_get_current_win()
local v = vim.wo[win_number]
local all_options = api.nvim_get_all_options_info()
local result = ""
for key, val in pairs(all_options) do
if val.global_local == false and val.scope == "win" then
result = result .. "|" .. key .. "=" .. tostring(v[key] or "<not set>")
end
end
print(result)

Related

Lua : Function pass memory variable link instead of value

Lua seems to pass parameters' memory adress to function instead of value
Is that a standard behaviour ?
Following code can be tested at https://www.lua.org/cgi-bin/demo
local t = {
Give = {"original"},
Etapes = {},
}
function check (obj)
for k, v in pairs(obj) do
if k == "Give" then
obj[k] = {"modified"}
end
end
-- return obj
end
print ("BEFORE t.Give[1]="..t.Give[1])
check(t)
print ("AFTER t.Give[1]="..t.Give[1])
print result :
BEFORE t.Give[1]=original
AFTER t.Give[1]=modified

Generating all combinations from a table in Lua

I'm trying to iterate through a table with a variable amount of elements and get all possible combinations, only using every element one time. I've landed on the solution below.
arr = {"a","b","c","d","e","f"}
function tablelen(table)
local count = 0
for _ in pairs(table) do
count = count + 1
end
return count
end
function spellsub(table,start,offset)
local str = table[start]
for i = start+offset, (tablelen(table)+1)-(start+offset) do
str = str..","..table[i+1]
end
return str
end
print(spellsub(arr,1,2)) -- Outputs: "a,d,e" correctly
print(spellsub(arr,2,2)) -- Outputs: "b" supposed to be "b,e,f"
I'm still missing some further functions, but I'm getting stuck with my current code. What is it that I'm missing? It prints correctly the first time but not the second?
A solution with a coroutine iterator called recursively:
local wrap, yield = coroutine.wrap, coroutine.yield
-- This function clones the array t and appends the item new to it.
local function append (t, new)
local clone = {}
for _, item in ipairs (t) do
clone [#clone + 1] = item
end
clone [#clone + 1] = new
return clone
end
--[[
Yields combinations of non-repeating items of tbl.
tbl is the source of items,
sub is a combination of items that all yielded combination ought to contain,
min it the minimum key of items that can be added to yielded combinations.
--]]
local function unique_combinations (tbl, sub, min)
sub = sub or {}
min = min or 1
return wrap (function ()
if #sub > 0 then
yield (sub) -- yield short combination.
end
if #sub < #tbl then
for i = min, #tbl do -- iterate over longer combinations.
for combo in unique_combinations (tbl, append (sub, tbl [i]), i + 1) do
yield (combo)
end
end
end
end)
end
for combo in unique_combinations {'a', 'b', 'c', 'd', 'e', 'f'} do
print (table.concat (combo, ', '))
end
For a tables with consecutive integer keys starting at 1 like yours you can simply use the length operator #. Your tablelen function is superfluous.
Using table as a local variable name shadows Lua's table library. I suggest you use tbl or some other name that does not prevent you from using table's methods.
The issue with your code can be solved by printing some values for debugging:
local arr = {"a","b","c","d","e","f"}
function spellsub(tbl,start,offset)
local str = tbl[start]
print("first str:", str)
print(string.format("loop from %d to %d", start+offset, #tbl+1-(start+offset)))
for i = start+offset, (#tbl+1)-(start+offset) do
print(string.format("tbl[%d]: %s", i+1, tbl[i+1]))
str = str..","..tbl[i+1]
end
return str
end
print(spellsub(arr,1,2)) -- Outputs: "a,d,e" correctly
print(spellsub(arr,2,2)) -- Outputs: "b" supposed to be "b,e,f"
prints:
first str: a
loop from 3 to 4
tbl[4]: d
tbl[5]: e
a,d,e
first str: b
loop from 4 to 3
b
As you see your second loop does not ran as the start value is already greater than the limit value. Hence you only print the first value b
I don't understand how your code is related to what you want to achieve so I'll leave it up to you to fix it.

table.insert doesn't trigger __index?

I made a custom table using metatables that automatically tracks sizing when elements are added. It works very well and removes the need for the # operator or the getn function.
However it has a problem. If you call table.insert, the function apparently never calls __index or __newindex. Thus, my table cannot know when elements are removed this way. I assume the problem is the same with table.remove as well.
How can I either:
Capture the event of insert and use my own function to do so
Throw an error if insert is called on my table.
Thanks
function Table_new()
local public = { }
local tbl = { }
local size = 0
function public.size()
return size
end
return setmetatable(public, {
__newindex = function(t, k, v)
local previous_v = tbl[k]
rawset(tbl, k, v)
if previous_v ~= nil then
if v == nil then
size = size - 1
end
elseif v ~= nil then
size = size + 1
end
end,
__index = tbl
})
end
local t = Table_new()
t[5] = "hi"
t[17] = "hello"
t[2] = "yo"
t[17] = nil
print(t.size()) -- prints 2
local z = Table_new()
table.insert(z, "hey")
table.insert(z, "hello")
table.insert(z, "yo")
print(z.size()) -- prints 1 -- why?
If you print k,v in __newindex, you'll see that k is always 1. This is because table.insert asks for the size of table to find where to insert the value. By default, it's at the end. You should add a __len metamethod. But perhaps this defeats your purposes (which are obscure to me).

Set value of 2 keys at same calling on a table

What am I looking for is a code like that.
local sometable = {
[1] = [2] = "abc",
}
So this is surely a wrong way to set 2 keys. ( returned an error )
You received an error because Lua doesn't have a syntax for setting multiple keys to a single value in a table constructor.
You have a few options, when using tables as arrays (sequences) you can omit the key:
local t = {'abc', 'abc'}
If you don't want to repeat the value, use a variable:
local init = 'abc'
local t = {init, init}
Or, write a function to do the initialization:
local function initialize(t, v, first, last)
first = first or 1
last = last or first
assert(first <= last, 'invalid first/last')
for i = first, last do
t[i] = v
end
return t
end
local t = initialize({}, 'abc', 1, 2)

lua misinterpreying check condition

I have a program which checks for conditions some variable field, like
if(tostring(field) == '0') then {do something}
if(tostring(field) == '1') then {do something}
if(tostring(field) == '2') then {do something}
But, i think lua is interpreting '0' and '1' as TRUE/FALSE values and not checking the corresponding if conditions properly. The condition executes properly for field == '2' condition.
How can i overcome this case? How can i make it work for check conditions '0' and '1'?
Thank You in advance!
In case you are wondering why i tagged wireshark, the if check condition is checking for a field in pcap file.
My lua code for reference is as follows:
#!/usr/bin/lua
do
local pkts = 0
local stat = {}
local file = io.open("luawrite","w")
local function init_listener()
local tap = Listener.new("wlan")
local src_addr = Field.new("wlan.sa")
local type = Field.new("wlan.fc.type")
local sub_type = Field.new("wlan.fc.subtype")
local frame_length = Field.new("frame.len")
local data_rate = Field.new("wlan.data_rate")
function tap.reset()
pkts = 0;
end
function tap.packet(pinfo, tvb)
local client = src_addr()
local stype = sub_type()
local ty = type()
local ts = tostring(pinfo.rel_ts)
local fl = frame_length()
rate = data_rate()
if(tostring(ty) == '0') then
file:write(tostring(ts), "\t", tostring(fl), "\t", tostring(rate), "\n")
end
end
end
init_listener()
end
The condition i am referring to 7th line from last line. If i give the condition tostring(ty) == '2', it works properly.
From the manual:
The condition expression of a control structure can return any value.
Both false and nil are considered false. All values different from nil
and false are considered true (in particular, the number 0 and the
empty string are also true).
Both the number 0 and the empty string evaluate to true, so it's definitely not mistaking the string "0" for false. I might avoid redefining type. Also, I think frame_type returns a number so you can get rid of the tostring() in the condition.
do
local pkts = 0
local stat = {}
local file = io.open("luawrite","w")
local function init_listener()
local tap = Listener.new("wlan")
local src_addr = Field.new("wlan.sa")
-- Changed function from type to frame_type
local frame_type = Field.new("wlan.fc.type")
local sub_type = Field.new("wlan.fc.subtype")
local frame_length = Field.new("frame.len")
local data_rate = Field.new("wlan.data_rate")
function tap.reset()
pkts = 0;
end
function tap.packet(pinfo, tvb)
local client = src_addr()
local stype = sub_type()
local ty = frame_type()
local ts = tostring(pinfo.rel_ts)
local fl = frame_length()
rate = data_rate()
-- skip the tostring
if ty == 0 then
file:write(tostring(ts), "\t", tostring(fl), "\t", tostring(rate), "\n")
end
end
end
init_listener()
end
If all else fails, try writing a line regardless of the frame type and write the frame type with it:
function tap.packet(pinfo, tvb)
local client = src_addr()
local stype = sub_type()
local ty = frame_type()
local ts = tostring(pinfo.rel_ts)
local fl = frame_length()
rate = data_rate()
file:write(tostring(ty), "\t", tostring(ts), "\t", tostring(rate), "\n")
end
Then you can see which frame types you're receiving.
As Corbin said, it's definitely not interpreting "0" and "1" as TRUE/FALSE. Wireshark runs the stock Lua interpreter, and Lua only considers nil and the boolean value of false as false values. Of course you're not really checking if they're false values, you're doing a string comparison of the string-ified value of the "wlan.fc.type" field value to the string "0" or the string "1" or whatever. The actual value you get for the "wlan.fc.type" field is a number, so as Corbin said there's no need to convert it to a string and string-compare it to a string of "0" or whatever... just compare them as numbers.
Regardless, stringifying both of them should have worked too (just been less efficient), so the odds are there simply isn't an 802.11 packet with a wlan.fc.type of 0 in your capture. A wlan.fc.type of 0 is a management frame, a 1 is a control frame, and a 2 is a data frame. So the odds are you're only capturing 802.11 data packets, which is why your comparison of the string-ified wlan.fc.type to the string "2" succeeds.
One way to find out is to open your capture file in wireshark, and put in a display filter for "wlan.fc.type == 0" and see if any packets are shown. If not, then you don't have any management packets.

Resources