From 9e3c418a03e10d1ab3f0517780f3dfc14be15362 Mon Sep 17 00:00:00 2001 From: Seth Barberee Date: Fri, 13 Dec 2019 00:10:10 -0600 Subject: [PATCH] add gears.table.cycle_value (#2942) --- lib/gears/table.lua | 42 +++++++++++++++++++ spec/gears/table_spec.lua | 29 +++++++++++++ .../awful/widget/layoutlist/popup.lua | 4 +- .../examples/text/gears/table/cycle_value.lua | 10 +++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 tests/examples/text/gears/table/cycle_value.lua diff --git a/lib/gears/table.lua b/lib/gears/table.lua index db038c2b..a06738aa 100644 --- a/lib/gears/table.lua +++ b/lib/gears/table.lua @@ -1,6 +1,13 @@ --------------------------------------------------------------------------- --- Table module for gears. -- +-- Examples +-- ======= +-- +-- Using `cycle_value`, you can cycle through values in a table. +-- When the end of the table is reached, `cycle_value` loops around to the beginning. +-- @DOC_text_gears_table_cycle_value_EXAMPLE@ +-- -- @utillib gears.table --------------------------------------------------------------------------- @@ -217,6 +224,41 @@ function gtable.clone(t, deep) return c end +--- Get the next (or previous) value from a table and cycle if necessary. +-- +-- If the table contains the same value multiple type (aka, is not a set), the +-- `first_index` has to be specified. +-- +-- @tparam table t The input table. +-- @param value A value from the table. +-- @tparam[opt=1] number step_size How many element forward (or backward) to pick. +-- @tparam[opt=nil] function filter An optional function. When it returns +-- `false`, the element are skipped until a match if found. It takes the value +-- as its sole parameter. +-- @tparam[opt=1] number start_at Where to start the lookup from. +-- @return The value. If no element match, then `nil` is returned. +-- @treturn number|nil The element (if any) key. +-- @staticfct gears.table.cycle_value +function gtable.cycle_value(t, value, step_size, filter, start_at) + local k = gtable.hasitem(t, value, true, start_at) + if not k then return end + + step_size = step_size or 1 + local new_key = gmath.cycle(#t, k + step_size) + + if filter and not filter(t[new_key]) then + for i=1, #t, step_size do + local k2 = gmath.cycle(#t, new_key + i) + if filter(t[k2]) then + return t[k2], k2 + end + end + return + end + + return t[new_key], new_key +end + --- Iterate over a table. -- -- Returns an iterator to cycle through all elements of a table that match a diff --git a/spec/gears/table_spec.lua b/spec/gears/table_spec.lua index 1c69f4fd..e4000c2b 100644 --- a/spec/gears/table_spec.lua +++ b/spec/gears/table_spec.lua @@ -42,6 +42,35 @@ describe("gears.table", function() end) end) + + describe("table.cycle_value", function() + it("nil argument", function() + local t = { "a", "b", "c", "d" } + local f = gtable.cycle_value(t, "a") + assert.is.same(f, "b") + end) + it("with step size", function() + local t = { "a", "b", "c", "d" } + local f = gtable.cycle_value(t, "a", 2) + assert.is.same(f, "c") + end) + it("b filter", function() + local t = { "a", "b", "c", "d" } + local f = gtable.cycle_value(t, "a", 1, function(i) return i == "b" end) + assert.is.equal(f, "b") + end) + it("e filter", function() + local t = { "a", "b", "c", "d" } + local f = gtable.cycle_value(t, "a", 1, function(i) return i == "e" end) + assert.is.equal(f, nil) + end) + it("b filter and step size", function() + local t = { "a", "b", "c", "d" } + local f = gtable.cycle_value(t, "b", 2, function(i) return i == "b" end) + assert.is.equal(f, nil) + end) + end) + describe("table.find_keys", function() it("nil argument", function() local t = { "a", "b", c = "c", "d" } diff --git a/tests/examples/awful/widget/layoutlist/popup.lua b/tests/examples/awful/widget/layoutlist/popup.lua index 7d3302e3..3aab7290 100644 --- a/tests/examples/awful/widget/layoutlist/popup.lua +++ b/tests/examples/awful/widget/layoutlist/popup.lua @@ -63,10 +63,10 @@ local modkey = "mod4" --DOC_HIDE stop_key = {"Escape", "Super_L", "Super_R"}, keybindings = { {{ modkey } , " " , function() - awful.layout.set(gears.table.iterate_value(ll.layouts, ll.current_layout, 1)) + awful.layout.set(gears.table.cycle_value(ll.layouts, ll.current_layout, 1)) end}, {{ modkey, "Shift" } , " " , function() - awful.layout.set(gears.table.iterate_value(ll.layouts, ll.current_layout, -1), nil) + awful.layout.set(gears.table.cycle_value(ll.layouts, ll.current_layout, -1), nil) end}, } } diff --git a/tests/examples/text/gears/table/cycle_value.lua b/tests/examples/text/gears/table/cycle_value.lua new file mode 100644 index 00000000..2a500d5e --- /dev/null +++ b/tests/examples/text/gears/table/cycle_value.lua @@ -0,0 +1,10 @@ +--DOC_GEN_OUTPUT --DOC_HIDE +local gears = require("gears") --DOC_HIDE + +local res = {"a", "b", "c", "d", "e"} + +for i=1, #res do + local k = res[i] + local v = gears.table.cycle_value(res, k, 1) + print(v) +end